pfds 10.2.2 heaps with efficient merging

13
Copyright © 2012 yuga 1 10.2.2 Heaps With Efficient Merging PFDS #11 復習 @yuga 2012-11-08 (初版) 2012-11-10 (2) 2012-11-30 (3)

Upload: shohei-murayama

Post on 13-Jul-2015

274 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 1

10.2.2

Heaps With Efficient Merging

PFDS #11 復習

@yuga

2012-11-08 (初版)

2012-11-10 (2版)

2012-11-30 (3版)

Page 2: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 2

動機

HeapをO(1)でマージしたいよ!

Page 3: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 3

Heapってなに?

こんなの。

HEAP :

module type HEAP = sig module Elem : ORDERED type heap val empty : heap val isEmpty : heap -> bool val insert : Elem.t * heap -> heap val merge : heap * heap -> heap val findMin : heap -> Elem.t val deleteMin : heap -> heap end

Page 4: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 4

解決の方針

HeapをO(1)でマージしたいなら

HeapをHeapで管理すればいいじゃない!

一方のHeap(BootStrapped type)の内部Heap(Primitive type)に もう一方のHeap(BootStrapped type)をそのまま入れる

BootStrapped type BootStrappedHeap

Primitive type これまでに登場したやつ

BootStrappedHeap同士の大小比較はルートノードで判定する

Page 5: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 5

図解: 解決の方針

絵にすると(ここでは例として Primitive type に BinomialHeap を使用)

merge

BinomialHeap の状態

8

3

5

4

2

7

9 6

9 6

7

BootStrappedHeap

BinomialHeap の状態

4

5

BinomialHeap

Page 6: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 6

図解: 解決の方針

merge結果

BootStrappedHeap 同士の大小比較は

ルートノードの値で判定

2

3

5

4

6 9

7

3

9 6

7

BinomialHeap の状態

4

5

Page 7: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 7

実行時間

これまでに登場したheapのだいたいの性能

insert / findMin : O(1)

merge / deleteMin : O(log n) … Worst-Case だったり Amortized だったり

それらを用いて作ると

BootStrappedHeap:

findMin は Primitive type に関係ない

⇒ O(1)

insert / merge は Primitive type の insert に依存

⇒ O(1)

deleteMin は Primitive type の findMin / deleteMin に依存

⇒ O(log n) … Worst-Case timeかどうかはPrimitive typeに依存

Page 8: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 8

実装

そんなわけでこれまでに登場したHeapを使って Heapを作ります。

本に載ってるコードは、例によって実際にはコンパイルが通らないSMLコード

本文はその意図するところの説明に費やされている

これをOCamlで動くものにかえるぜ

Page 9: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 9

難しいOCaml

OCamlのモジュール難しい orz

https://twitter.com/camloeba/status/265702576954171392

Page 10: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 10

実装: OCamlでの完成形

open Ordered;; open Heap;; module BootStrappedHeap = functor (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element) -> functor (Element : ORDERED) -> struct module Elem = Element exception Empty module rec BootStrappedElem : sig type t = E | H of Elem.t * PrimH.heap include ORDERED with type t := t end = struct type t = E | H of Elem.t * PrimH.heap let eq = function (* snip *) end and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem) include BootStrappedElem type heap = t let empty = E let isEmpty = function (* snip *) end open ScheduledBinomialHeap;; module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int)

Ocamlで実際に動かしてみたやつ: https://github.com/yuga/readpfds/blob/master/OCaml/bootStrappedHeap.ml

最後 functor が HEAP を返すように

型を明示したいけど書けない

もっと別の書き方もある??

追記: あった => P13へ

Page 11: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 11

実装: メモ #1 (MakeHについて)

open Ordered;; open Heap;; module BootStrappedHeap = functor (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element) -> functor (Element : ORDERED) -> struct module Elem = Element exception Empty module rec BootStrappedElem : sig type t = E | H of Elem.t * PrimH.heap include ORDERED with type t := t end = struct type t = E | H of Elem.t * PrimH.heap let eq = function (* snip *) end and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem) include BootStrappedElem type heap = t let empty = E let isEmpty = function (* snip *) end open ScheduledBinomialHeap;; module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int)

ScheduledBinomialHeap の型は

functor (Element : ORDERED) -> HEAP with module Elem = Element

MakeH には ORDERED型のパラメタを受け取りHEAP を返すfunctorである

ScheduledBinomialHeap がアサインされる

結果、MakeH により BootStrappedElem 型の要素を持つ HEAP が作られる

Page 12: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 12

実装: メモ #2

open Ordered;; open Heap;; module BootStrappedHeap = functor (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element) -> functor (Element : ORDERED) -> struct module Elem = Element exception Empty module rec BootStrappedElem : sig type t = E | H of Elem.t * PrimH.heap include ORDERED with type t := t end = struct type t = E | H of Elem.t * PrimH.heap let eq = function (* snip *) end and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem) include BootStrappedElem type heap = t let empty = E let isEmpty = function (* snip *) end open ScheduledBinomialHeap;; module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int)

BootStrappedHeap が ORDERED のシグネチャを持つ

Int を要素として格納するよう指定

Element には Int がアサインされる

HEAP は要素のシグネチャを Elem で持つ

Elem.t の型は int になる

PrimH は MakeH により作られる HEAP

BootStrappedElem と PrimH は相互依存するので rec 指定

BootStrappedElem は HEAP に格納される要素になるので、

ORDERED のシグネチャを実装する

BootStrappedHeap は、BootStrappedElem 内で定義した型 t が

自分の型 heap でもあるので、include で自分の中に展開し heap にアサイン

Page 13: PFDS 10.2.2 heaps with efficient merging

Copyright © 2012 yuga 13

実装: OCamlでの完成形(その2)

open Ordered;; open Heap;; module BootStrappedHeap (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element) (Element : ORDERED) : (HEAP with module Elem = Element) = struct module Elem = Element exception Empty module rec BootStrappedElem : sig type t = E | H of Elem.t * PrimH.heap include ORDERED with type t := t end = struct type t = E | H of Elem.t * PrimH.heap let eq = function (* snip *) end and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem) include BootStrappedElem type heap = t let empty = E let isEmpty = function (* snip *) end open ScheduledBinomialHeap;; module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int)

Ocamlで実際に動かしてみたやつ: https://github.com/yuga/readpfds/blob/master/OCaml/bootStrappedHeap.ml

こう書くことができた