Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Deque with Haskel

1,050 views

Published on

Simple Deque implementation with Haskell
Haskellで両端キューを書いてみたはなし
JOIss2015 珠玉班

Published in: Science
  • Be the first to comment

Deque with Haskel

  1. 1. データ構造 with Haskell
  2. 2. 目次 ● Stack ● Queue ● Deque
  3. 3. 目次 ● Stack ● Queue ● Deque ● 全部配列を使えば一瞬じゃないか! いいかげんにしろ!
  4. 4. 残念ながら 配列なんて無いよ
  5. 5. Haskellのデータ構造 ● 配列は一応あるよ – ただし代入に O(N) かかる
  6. 6. Haskellのデータ構造 ● リストというのを使います ● 次の操作が可能 – 先頭に値を追加 O(1) – 先頭から削除 O(1) – n番目にアクセス O(n) ● 厳密にはちょっと違うけどだいたいあってる
  7. 7. Haskellのリスト ● [3, 1, 4, 1, 5] –-リストの例 ● 追加 – 9 : [3, 1, 4, 1, 5] → [9, 3, 1, 4, 1, 5] ● 先頭を得る – head [3, 1, 4, 1, 5] → 3 ● 先頭以外を得る – tail [3, 1, 4, 1, 5] → [1, 4, 1, 5] – tail [1] → [ ] –- 空のリスト
  8. 8. Haskellのリスト ● 先頭にくっつける (:) ● 先頭を参照する head ● 先頭以外を参照する tail ● これらは以降たくさん出てくるのでよく覚えて いてね
  9. 9. 1つめのデータ構造 Stack
  10. 10. Stack ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (push) – 列の先頭から値を取り出す (pop)
  11. 11. Stack:図示 ● 空のStackがあるじゃろ – 左側が先頭
  12. 12. Stack:図示 ● push(4) 4
  13. 13. Stack:図示 ● push(4), push(1) 41
  14. 14. Stack:図示 ● push(4), push(1), push(1) 411
  15. 15. Stack:図示 ● push(4), push(1), push(1), pop() 41 1
  16. 16. Stack:図示 ● push(4), push(1), push(1), pop(), push(5) 4155
  17. 17. Stack ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (push) – 列の先頭から値を取り出す (pop)
  18. 18. Stack ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (push) – 列の先頭から値を取り出す (pop) ● すごい既視感
  19. 19. Haskellのデータ構造 (再掲) ● リストというのを使います ● 次の操作が可能 – 先頭に値を追加 O(1) – 先頭から削除 O(1) – n番目にアクセス O(n) ● 厳密にはちょっと違うけどだいたいあってる
  20. 20. Haskellのデータ構造 (再掲) ● リストというのを使います ● 次の操作が可能 – 先頭に値を追加 O(1) – 先頭から削除 O(1) – n番目にアクセス O(n) ● 厳密にはちょっと違うけどだいたいあってる
  21. 21. Stack ● スタック ● リストをそのまま使える – やったぜ
  22. 22. Stack: 実装 (ソースコードをここに書く) (説明をここに書く)
  23. 23. Stack: 実装 Data Stack a = S [a] Stack型の定義
  24. 24. Stack: 実装 Data Stack a = S [a] push (S xs) x = S (x:xs) pushの定義
  25. 25. Stack: 実装 Data Stack a = S [a] push (S xs) x = S (x:xs) pop (x:xs) = (x, S xs) popの定義
  26. 26. Stack: 実装 Data Stack a = S [a] push (S xs) x = S (x:xs) pop (x:xs) = (x, S xs) 空のStackをpopしないことは 良心にまかせる
  27. 27. Stack: 実装 Data Stack a = S [a] push (S xs) x = S (x:xs) pop (x:xs) = (x, S xs) 完成
  28. 28. 1つめのデータ構造 Queue
  29. 29. Queue ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (push) – 列の末尾から値を取り出す (pop)
  30. 30. Queue: 図示 ● 空のQueueがあるじゃろ – 左側から入って、右側から出る
  31. 31. Queue: 図示 ● push(3) 3
  32. 32. Queue: 図示 ● push(3), push(7) 37
  33. 33. Queue: 図示 ● push(3), push(7), push(2) 372
  34. 34. Queue: 図示 ● push(3), push(7), push(2), pop() 3 72
  35. 35. Queue: 図示 ● push(3), push(7), push(2), pop() 72
  36. 36. Queue: 図示 ● push(3), push(7), push(2), pop(), push(9) 729
  37. 37. Queue: 図示 ● push(3), push(7), push(2), pop(), push(9) pop() 7 29
  38. 38. Queue ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (push) – 列の末尾から値を取り出す (pop)
  39. 39. Queue ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (push) – 列の末尾から値を取り出す (pop) – リストの末尾の操作は厄介
  40. 40. Queue ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (push) – 列の末尾から値を取り出す (pop) – リストの末尾の操作は厄介 – しかしデータ構造の申し子である皆さんな ら対処法をすぐに思いつくはず
  41. 41. 有名なことわざ QueueはStack2つで作れる
  42. 42. Queue: 図示 ● 空のQueueの下に2つのStackがあるじゃろ
  43. 43. Queue: 図示 ● push(3) 3 3
  44. 44. Queue: 図示 ● push(3), push(5) 3 3 5 5
  45. 45. Queue: 図示 ● push(3), push(5), push(1) 3 35 5 1 1
  46. 46. Queue: 図示 ● push(3), push(5), push(1), pop() 3 35 5 1 1
  47. 47. Queue: 図示 ● push(3), push(5), push(1), pop() ● pop時右側が空だったらエイヤッする 3 35 5 1 1
  48. 48. Queue: 図示 ● push(3), push(5), push(1), pop() 3 35 5 1 1
  49. 49. Queue: 図示 ● push(3), push(5), push(1), pop() 5 5 1 1
  50. 50. Queue: 図示 ● push(3), push(5), push(1), pop(), push(2) 5 5 1 1 2 2
  51. 51. Queue: 図示 ● push(3), push(5), push(1), pop(), push(2), pop() 5 5 1 1 2 2
  52. 52. Queue(Stack×2) ● Stackはさっき実装したばかりだしやるだけ じゃん! ● 一番ややこしいのはpopするときに右側の Stackが空だった時
  53. 53. Queue(Stack×2) ● Stackはさっき実装したばかりだしやるだけ じゃん! ● 一番ややこしいのはpopするときに右側の Stackが空だった時 351
  54. 54. Queue(Stack×2) ● Stackはさっき実装したばかりだしやるだけ じゃん! ● 一番ややこしいのはpopするときに右側の Stackが空だった時 351 エイヤッ
  55. 55. Queue(Stack×2) ● Stackはさっき実装したばかりだしやるだけ じゃん! ● 一番ややこしいのはpopするときに右側の Stackが空だった時 ● Stackがただのリストであったことを思い出す と、エイヤッはただのリスト反転 – 標準で reverseという関数がある
  56. 56. Queue: 実装 (実装をここに書く) (説明をここに書く)
  57. 57. Queue: 実装 Queue a = Q [a] [a] Queueの型を定義 リスト2つ
  58. 58. Queue: 実装 Queue a = Q [a] [a] push (Q xs ys) x = Q (x:xs) ys push の実装 (Stackと同様)
  59. 59. Queue: 実装 Queue a = Q [a] [a] push (Q xs ys) x = Q (x:xs) ys pop (Q xs y:ys) = (y (Q xs ys)) 右側が空じゃない時のpop
  60. 60. Queue: 実装 Queue a = Q [a] [a] push (Q xs ys) x = Q (x:xs) ys pop (Q xs y:ys) = (y (Q xs ys)) pop (Q xs []) = pop(Q [] (reverse xs)) 右側が空の時のpop
  61. 61. 3つめのデータ構造 Deque
  62. 62. Deque ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (pushF) – 列の末尾に値を追加  (pushB) – 列の先頭から値を取り出す (popF) – 列の末尾から値を取り出す (popB)
  63. 63. Deque: 図示 ● ここに空のDequeがあるじゃろ – 左が先頭(Front), 右が末尾 (Back)
  64. 64. Deque: 図示 ● pushF(3) 3
  65. 65. Deque: 図示 ● pushF(3), pushB(4) 3 4
  66. 66. Deque: 図示 ● pushF(3), pushB(4), pushF(5) 3 45
  67. 67. Deque: 図示 ● pushF(3), pushB(4), pushF(5), popB() 3 4 5 4
  68. 68. Deque: 図示 ● pushF(3), pushB(4), pushF(5), popB() 35
  69. 69. Deque: 図示 ● pushF(3), pushB(4), pushF(5), popB(), popF() 3 5
  70. 70. Deque: 図示 ● pushF(3), pushB(4), pushF(5), popB(), popF() 3
  71. 71. Deque: 図示 ● pushF(3), pushB(4), pushF(5), popB(), popF() pushB(4) 3 4
  72. 72. Deque: 図示 ● pushF(3), pushB(4), pushF(5), popB(), popF() pushB(4), pushF(3) 3 433
  73. 73. Deque ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (pushF) – 列の末尾に値を追加  (pushB) – 列の先頭から値を取り出す (popF) – 列の末尾から値を取り出す (popB)
  74. 74. Deque ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (pushF) – 列の末尾に値を追加  (pushB) – 列の先頭から値を取り出す (popF) – 列の末尾から値を取り出す (popB)
  75. 75. Queue ● 次の操作に対応したデータ構造 – 列の先頭に値を追加  (pushF) – 列の末尾に値を追加  (pushB) – 列の先頭から値を取り出す (popF) – 列の末尾から値を取り出す (popB)
  76. 76. 有名なことわざ DequeはStack2つで作れる
  77. 77. Deque(Stack×2): 図示 ● 空のDequeの下にStackが2つあるじゃろ – 左が先頭(Front), 右が末尾 (Back)
  78. 78. 432 Deque(Stack×2): 図示 ● pushF(1), pushF(2), pushF(3), pushF(4) 4321 1
  79. 79. 432 Deque(Stack×2): 図示 ● pushF(1), pushF(2), pushF(3), pushF(4) popB() 4 321 1
  80. 80. 32 Deque(Stack×2): 図示 ● pushF(1), pushF(2), pushF(3), pushF(4) popB() 4 321 1 エイヤッ 4
  81. 81. 32 Deque(Stack×2): 図示 ● pushF(1), pushF(2), pushF(3), pushF(4) popB() 4 321 1 4
  82. 82. 32 Deque(Stack×2): 図示 ● pushF(1), pushF(2), pushF(3), pushF(4) popB() 321 1
  83. 83. Deque(Stack×2) ● Stackはさっき実装したばかりだしやるだけ じゃん!(デジャヴ) ● 一番ややこしいのはpopするときにしたい方 のStackが空だった時 (デジャヴ) 4321
  84. 84. 321 4 Deque(Stack×2) ● Stackはさっき実装したばかりだしやるだけ じゃん!(デジャヴ) ● 一番ややこしいのはpopするときにしたい方 のStackが空だった時 (デジャヴ) エイヤッ
  85. 85. Deque(Stack×2) ● Stackはさっき実装したばかりだしやるだけじゃん! (デジャヴ) ● 一番ややこしいのはpopするときにしたい方のStack が空だった時 (デジャヴ) ● エイヤッは空じゃないStackの中身を半分ずつにわけ る操作 – リストの最初 k 個分をとりだす take – リストの最初 k 個を除いたリストを得る drop – これらを使えば便利
  86. 86. Deque(Stack×2) ● Stackはさっき実装したばかりだしやるだけ じゃん!(デジャヴ) ● 一番ややこしいのはpopするときにしたい方 のStackが空だった時 (デジャヴ) ● エイヤッは空じゃないStackの中身を半分ずつに わける操作 – 空じゃない方の奥側半分を逆転して空の 方につっこむ –
  87. 87. Deque: 実装 (実装をここに書く) (説明をここに書く)
  88. 88. Deque: 実装 Deque a = D [a] [a] pushF (D xs ys) x = D (x:xs) ys pushB (D xs ys) y = D xs (y:ys) pushFとpushB (簡単)
  89. 89. Deque: 実装 Deque a = D [a] [a] popF (D x:xs ys) = (x, (D xs ys)) 左側が空じゃない時のpopF
  90. 90. Deque: 実装 Deque a = D [a] [a] popF (D x:xs ys) = (x, (D xs ys)) popF (D [] ys) = popF (D lh rh) where lh = take h ys rh = reverse (drop h ys) h = (length ys) `div` 2 左側が空の時のpopF
  91. 91. Deque: 実装 Deque a = D [a] [a] popB (D xs y:ys) = (y, (D xs ys)) popB (D xs []) = popB (D lh rh) where lh = reverse (drop h xs) rh = take h xs h = (length xs) `div` 2 popBも同様
  92. 92. クリックしてタイトルを挿入! やったぜ
  93. 93. サンプルコード ● サンプルコードはこちら ● https://github.com/catupper/JOISS2015/blob/master/Queue /Deque.hs

×