View
277
Download
0
Category
Preview:
Citation preview
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版)
Copyright © 2012 yuga 2
動機
HeapをO(1)でマージしたいよ!
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
Copyright © 2012 yuga 4
解決の方針
HeapをO(1)でマージしたいなら
HeapをHeapで管理すればいいじゃない!
一方のHeap(BootStrapped type)の内部Heap(Primitive type)に もう一方のHeap(BootStrapped type)をそのまま入れる
BootStrapped type BootStrappedHeap
Primitive type これまでに登場したやつ
BootStrappedHeap同士の大小比較はルートノードで判定する
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
Copyright © 2012 yuga 6
図解: 解決の方針
merge結果
BootStrappedHeap 同士の大小比較は
ルートノードの値で判定
2
3
5
4
6 9
7
3
9 6
7
BinomialHeap の状態
4
5
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に依存
Copyright © 2012 yuga 8
実装
そんなわけでこれまでに登場したHeapを使って Heapを作ります。
本に載ってるコードは、例によって実際にはコンパイルが通らないSMLコード
本文はその意図するところの説明に費やされている
これをOCamlで動くものにかえるぜ
Copyright © 2012 yuga 9
難しいOCaml
OCamlのモジュール難しい orz
https://twitter.com/camloeba/status/265702576954171392
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へ
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 が作られる
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 にアサイン
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
こう書くことができた
Recommended