93
データ構造 with Haskell

Deque with Haskel

Embed Size (px)

Citation preview

Page 1: Deque with Haskel

データ構造with Haskell

Page 2: Deque with Haskel

目次

● Stack● Queue● Deque

Page 3: Deque with Haskel

目次

● Stack● Queue● Deque

● 全部配列を使えば一瞬じゃないか!いいかげんにしろ!

Page 4: Deque with Haskel

残念ながら

配列なんて無いよ

Page 5: Deque with Haskel

Haskellのデータ構造

● 配列は一応あるよ

– ただし代入に O(N) かかる

Page 6: Deque with Haskel

Haskellのデータ構造

● リストというのを使います● 次の操作が可能

– 先頭に値を追加 O(1)– 先頭から削除 O(1)– n番目にアクセス O(n)

● 厳密にはちょっと違うけどだいたいあってる

Page 7: Deque with Haskel

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] → [ ] –- 空のリスト

Page 8: Deque with Haskel

Haskellのリスト

● 先頭にくっつける (:)● 先頭を参照する head● 先頭以外を参照する tail

● これらは以降たくさん出てくるのでよく覚えていてね

Page 9: Deque with Haskel

1つめのデータ構造

Stack

Page 10: Deque with Haskel

Stack

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (push)– 列の先頭から値を取り出す (pop)

Page 11: Deque with Haskel

Stack:図示

● 空のStackがあるじゃろ– 左側が先頭

Page 12: Deque with Haskel

Stack:図示

● push(4)

4

Page 13: Deque with Haskel

Stack:図示

● push(4), push(1)

41

Page 14: Deque with Haskel

Stack:図示

● push(4), push(1), push(1)

411

Page 15: Deque with Haskel

Stack:図示

● push(4), push(1), push(1), pop()

411

Page 16: Deque with Haskel

Stack:図示

● push(4), push(1), push(1), pop(), push(5)

4155

Page 17: Deque with Haskel

Stack

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (push)– 列の先頭から値を取り出す (pop)

Page 18: Deque with Haskel

Stack

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (push)– 列の先頭から値を取り出す (pop)

● すごい既視感

Page 19: Deque with Haskel

Haskellのデータ構造 (再掲)

● リストというのを使います● 次の操作が可能

– 先頭に値を追加 O(1)– 先頭から削除 O(1)– n番目にアクセス O(n)

● 厳密にはちょっと違うけどだいたいあってる

Page 20: Deque with Haskel

Haskellのデータ構造 (再掲)

● リストというのを使います● 次の操作が可能

– 先頭に値を追加 O(1)– 先頭から削除 O(1)– n番目にアクセス O(n)

● 厳密にはちょっと違うけどだいたいあってる

Page 21: Deque with Haskel

Stack

● スタック● リストをそのまま使える

– やったぜ

Page 22: Deque with Haskel

Stack: 実装

(ソースコードをここに書く)

(説明をここに書く)

Page 23: Deque with Haskel

Stack: 実装

Data Stack a = S [a]

Stack型の定義

Page 24: Deque with Haskel

Stack: 実装

Data Stack a = S [a]

push (S xs) x = S (x:xs)

pushの定義

Page 25: Deque with Haskel

Stack: 実装

Data Stack a = S [a]

push (S xs) x = S (x:xs)

pop (x:xs) = (x, S xs)

popの定義

Page 26: Deque with Haskel

Stack: 実装

Data Stack a = S [a]

push (S xs) x = S (x:xs)

pop (x:xs) = (x, S xs)

空のStackをpopしないことは良心にまかせる

Page 27: Deque with Haskel

Stack: 実装

Data Stack a = S [a]

push (S xs) x = S (x:xs)

pop (x:xs) = (x, S xs)

完成

Page 28: Deque with Haskel

1つめのデータ構造

Queue

Page 29: Deque with Haskel

Queue

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (push)– 列の末尾から値を取り出す (pop)

Page 30: Deque with Haskel

Queue: 図示

● 空のQueueがあるじゃろ

– 左側から入って、右側から出る

Page 31: Deque with Haskel

Queue: 図示

● push(3)

3

Page 32: Deque with Haskel

Queue: 図示

● push(3), push(7)

37

Page 33: Deque with Haskel

Queue: 図示

● push(3), push(7), push(2)

372

Page 34: Deque with Haskel

Queue: 図示

● push(3), push(7), push(2), pop()

372

Page 35: Deque with Haskel

Queue: 図示

● push(3), push(7), push(2), pop()

72

Page 36: Deque with Haskel

Queue: 図示

● push(3), push(7), push(2), pop(), push(9)

729

Page 37: Deque with Haskel

Queue: 図示

● push(3), push(7), push(2), pop(), push(9)pop()

729

Page 38: Deque with Haskel

Queue

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (push)– 列の末尾から値を取り出す (pop)

Page 39: Deque with Haskel

Queue

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (push)– 列の末尾から値を取り出す (pop)– リストの末尾の操作は厄介

Page 40: Deque with Haskel

Queue

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (push)– 列の末尾から値を取り出す (pop)– リストの末尾の操作は厄介– しかしデータ構造の申し子である皆さんな

ら対処法をすぐに思いつくはず

Page 41: Deque with Haskel

有名なことわざ

QueueはStack2つで作れる

Page 42: Deque with Haskel

Queue: 図示

● 空のQueueの下に2つのStackがあるじゃろ

Page 43: Deque with Haskel

Queue: 図示

● push(3)

3

3

Page 44: Deque with Haskel

Queue: 図示

● push(3), push(5)

3

3

5

5

Page 45: Deque with Haskel

Queue: 図示

● push(3), push(5), push(1)

3

35

5

1

1

Page 46: Deque with Haskel

Queue: 図示

● push(3), push(5), push(1), pop()

3

35

5

1

1

Page 47: Deque with Haskel

Queue: 図示

● push(3), push(5), push(1), pop()● pop時右側が空だったらエイヤッする

3

35

5

1

1

Page 48: Deque with Haskel

Queue: 図示

● push(3), push(5), push(1), pop()

3

35

5

1

1

Page 49: Deque with Haskel

Queue: 図示

● push(3), push(5), push(1), pop()

5

5

1

1

Page 50: Deque with Haskel

Queue: 図示

● push(3), push(5), push(1), pop(), push(2)

5

5

1

1

2

2

Page 51: Deque with Haskel

Queue: 図示

● push(3), push(5), push(1), pop(), push(2), pop()

5

5

1

1

2

2

Page 52: Deque with Haskel

Queue(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!

● 一番ややこしいのはpopするときに右側のStackが空だった時

Page 53: Deque with Haskel

Queue(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!

● 一番ややこしいのはpopするときに右側のStackが空だった時

351

Page 54: Deque with Haskel

Queue(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!

● 一番ややこしいのはpopするときに右側のStackが空だった時

351

エイヤッ

Page 55: Deque with Haskel

Queue(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!

● 一番ややこしいのはpopするときに右側のStackが空だった時

● Stackがただのリストであったことを思い出すと、エイヤッはただのリスト反転

– 標準で reverseという関数がある

Page 56: Deque with Haskel

Queue: 実装

(実装をここに書く)

(説明をここに書く)

Page 57: Deque with Haskel

Queue: 実装

Queue a = Q [a] [a]

Queueの型を定義 リスト2つ

Page 58: Deque with Haskel

Queue: 実装

Queue a = Q [a] [a]

push (Q xs ys) x = Q (x:xs) ys

push の実装 (Stackと同様)

Page 59: Deque with Haskel

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

Page 60: Deque with Haskel

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

Page 61: Deque with Haskel

3つめのデータ構造

Deque

Page 62: Deque with Haskel

Deque

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (pushF)– 列の末尾に値を追加  (pushB)– 列の先頭から値を取り出す (popF)– 列の末尾から値を取り出す (popB)

Page 63: Deque with Haskel

Deque: 図示

● ここに空のDequeがあるじゃろ

– 左が先頭(Front), 右が末尾 (Back)

Page 64: Deque with Haskel

Deque: 図示

● pushF(3)

3

Page 65: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4)

3 4

Page 66: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4), pushF(5)

3 45

Page 67: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4), pushF(5), popB()

34

54

Page 68: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4), pushF(5), popB()

35

Page 69: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4), pushF(5), popB(), popF()

35

Page 70: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4), pushF(5), popB(), popF()

3

Page 71: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4), pushF(5), popB(), popF()pushB(4)

3 4

Page 72: Deque with Haskel

Deque: 図示

● pushF(3), pushB(4), pushF(5), popB(), popF()pushB(4), pushF(3)

3 433

Page 73: Deque with Haskel

Deque

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (pushF)– 列の末尾に値を追加  (pushB)– 列の先頭から値を取り出す (popF)– 列の末尾から値を取り出す (popB)

Page 74: Deque with Haskel

Deque

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (pushF)– 列の末尾に値を追加  (pushB)– 列の先頭から値を取り出す (popF)– 列の末尾から値を取り出す (popB)

Page 75: Deque with Haskel

Queue

● 次の操作に対応したデータ構造

– 列の先頭に値を追加  (pushF)– 列の末尾に値を追加  (pushB)– 列の先頭から値を取り出す (popF)– 列の末尾から値を取り出す (popB)

Page 76: Deque with Haskel

有名なことわざ

DequeはStack2つで作れる

Page 77: Deque with Haskel

Deque(Stack×2): 図示

● 空のDequeの下にStackが2つあるじゃろ

– 左が先頭(Front), 右が末尾 (Back)

Page 78: Deque with Haskel

432

Deque(Stack×2): 図示

● pushF(1), pushF(2), pushF(3), pushF(4)

4321

1

Page 79: Deque with Haskel

432

Deque(Stack×2): 図示

● pushF(1), pushF(2), pushF(3), pushF(4)popB()

4321

1

Page 80: Deque with Haskel

32

Deque(Stack×2): 図示

● pushF(1), pushF(2), pushF(3), pushF(4)popB()

4321

1エイヤッ

4

Page 81: Deque with Haskel

32

Deque(Stack×2): 図示

● pushF(1), pushF(2), pushF(3), pushF(4)popB()

4321

14

Page 82: Deque with Haskel

32

Deque(Stack×2): 図示

● pushF(1), pushF(2), pushF(3), pushF(4)popB()

321

1

Page 83: Deque with Haskel

Deque(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!(デジャヴ)

● 一番ややこしいのはpopするときにしたい方のStackが空だった時 (デジャヴ)

4321

Page 84: Deque with Haskel

321 4

Deque(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!(デジャヴ)

● 一番ややこしいのはpopするときにしたい方のStackが空だった時 (デジャヴ)

エイヤッ

Page 85: Deque with Haskel

Deque(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!(デジャヴ)

● 一番ややこしいのはpopするときにしたい方のStackが空だった時 (デジャヴ)

● エイヤッは空じゃないStackの中身を半分ずつにわける操作

– リストの最初 k 個分をとりだす take– リストの最初 k 個を除いたリストを得る drop– これらを使えば便利

Page 86: Deque with Haskel

Deque(Stack×2)

● Stackはさっき実装したばかりだしやるだけじゃん!(デジャヴ)

● 一番ややこしいのはpopするときにしたい方のStackが空だった時 (デジャヴ)

● エイヤッは空じゃないStackの中身を半分ずつにわける操作

– 空じゃない方の奥側半分を逆転して空の方につっこむ

Page 87: Deque with Haskel

Deque: 実装

(実装をここに書く)

(説明をここに書く)

Page 88: Deque with Haskel

Deque: 実装

Deque a = D [a] [a]

pushF (D xs ys) x = D (x:xs) yspushB (D xs ys) y = D xs (y:ys)

pushFとpushB (簡単)

Page 89: Deque with Haskel

Deque: 実装

Deque a = D [a] [a]

popF (D x:xs ys) = (x, (D xs ys))

左側が空じゃない時のpopF

Page 90: Deque with Haskel

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

Page 91: Deque with Haskel

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も同様

Page 92: Deque with Haskel

クリックしてタイトルを挿入!

やったぜ

Page 93: Deque with Haskel

サンプルコード

● サンプルコードはこちら

● https://github.com/catupper/JOISS2015/blob/master/Queue/Deque.hs