SlideShare a Scribd company logo
PFDS #11 復習



               10.2.2
               Heaps With Efficient Merging


               @yuga
               2012-11-08 (初版)
               2012-11-10 (2版)
               2012-11-30 (3版)
Copyright © 2012 yuga                         1
動機


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




Copyright © 2012 yuga   2
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                                             3
解決の方針

   HeapをO(1)でマージしたいなら
   HeapをHeapで管理すればいいじゃない!


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

        BootStrapped type   BootStrappedHeap

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

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

Copyright © 2012 yuga                                   4
図解: 解決の方針

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

                                    BinomialHeap の状態                  BinomialHeap の状態
                            2                                     3
                                           9   6                             4


                                               7                             5
                                                                  4
                        9       6
                                                                                 merge
                                                                  5
                                7




                                       8

                                               BootStrappedHeap

                                               BinomialHeap
Copyright © 2012 yuga                                                                    5
図解: 解決の方針

   merge結果                         2

                                           BinomialHeap の状態
   BootStrappedHeap 同士の大小比較は
                                   3
   ルートノードの値で判定                                         3


                                   4
                                               6       9


                                               7

                                   5




                                                   4

                               6       9
                                                   5




                               7




Copyright © 2012 yuga                                         6
実行時間

   これまでに登場した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                                                  7
実装

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

        本に載ってるコードは、例によって実際にはコンパイルが通らない
         SMLコード
        本文はその意図するところの説明に費やされている
        これをOCamlで動くものにかえるぜ




Copyright © 2012 yuga                     8
難しいOCaml

   OCamlのモジュール難しい orz




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




Copyright © 2012 yuga                                                            9
実装: 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                                           最後 functor が HEAP を返すように
                type t = E
                       | H of Elem.t * PrimH.heap                                         型を明示したいけど書けない
                include ORDERED with type t := t
                                                                                          もっと別の書き方もある??
              end = struct
                type t = E                                                                追記: あった => P13へ
                       | 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
Copyright © 2012 yuga                                                                                                     10
実装: メモ #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      MakeH には ORDERED型のパラメタを受け取りHEAP を返すfunctorである
              end = struct
                type t = E                            ScheduledBinomialHeap がアサインされる
                       | H of Elem.t * PrimH.heap     結果、MakeH により BootStrappedElem 型の要素を持つ HEAP が作られる
                let eq = function
                (* snip *)
              end
              and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem)

              include BootStrappedElem

              type heap = t
              let empty = E
                                                ScheduledBinomialHeap の型は
             let isEmpty = function
             (* snip *)                         functor (Element : ORDERED) -> HEAP with module Elem = Element
           end

           open ScheduledBinomialHeap;;
           module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int)



Copyright © 2012 yuga                                                                                                  11
実装: メモ #2
           open Ordered;;
           open Heap;;

           module BootStrappedHeap
            = functor (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element)
           -> functor (Element : ORDERED)
           -> struct                                Element には Int がアサインされる
             module Elem = Element
             exception Empty                        HEAP は要素のシグネチャを Elem で持つ

              module rec BootStrappedElem : sig
                type t = E                                    Elem.t の型は int になる
                       | H of Elem.t * PrimH.heap
                                                              PrimH は MakeH により作られる HEAP
                include ORDERED with type t := t
              end = struct                                    BootStrappedElem と PrimH は相互依存するので rec 指定
                type t = E
                       | H of Elem.t * PrimH.heap             BootStrappedElem は HEAP に格納される要素になるので、
                let eq = function
                (* snip *)                                    ORDERED のシグネチャを実装する
              end
              and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem)

              include BootStrappedElem         BootStrappedHeap は、BootStrappedElem 内で定義した型 t が
              type heap = t                    自分の型 heap でもあるので、include で自分の中に展開し heap にアサイン
              let empty = E

             let isEmpty = function                                 BootStrappedHeap が ORDERED のシグネチャを持つ
             (* snip *)
           end                                                      Int を要素として格納するよう指定

           open ScheduledBinomialHeap;;
           module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int)



Copyright © 2012 yuga                                                                                                  12
実装: 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
Copyright © 2012 yuga                                                                                                     13

More Related Content

PDF
ちょっと詳しくJavaScript 第3回【prototype】
PDF
新しい並列for構文のご提案
PDF
Boost.Coroutine
PDF
Boost.SIMD
PDF
20分くらいでわかった気分になれるC++20コルーチン
PDF
unique_ptrにポインタ以外のものを持たせるとき
ちょっと詳しくJavaScript 第3回【prototype】
新しい並列for構文のご提案
Boost.Coroutine
Boost.SIMD
20分くらいでわかった気分になれるC++20コルーチン
unique_ptrにポインタ以外のものを持たせるとき

What's hot (8)

PDF
C++14 Overview
PPTX
Visual C++で使えるC++11
PDF
The Why and How of Java8 at LINE Fukuoka
PDF
C++ ポインタ ブートキャンプ
PDF
C++による数値解析の並列化手法
PPTX
競技プログラミングのためのC++入門
PDF
組み込みでこそC++を使う10の理由
PDF
Move semantics
C++14 Overview
Visual C++で使えるC++11
The Why and How of Java8 at LINE Fukuoka
C++ ポインタ ブートキャンプ
C++による数値解析の並列化手法
競技プログラミングのためのC++入門
組み込みでこそC++を使う10の理由
Move semantics
Ad

Similar to PFDS 10.2.2 heaps with efficient merging (20)

PDF
PFDS 5.5 Pairing heap
PDF
PFDS 10.2.1 lists with efficient catenation
PDF
PFDS 11.2 catenable double ended queue
PDF
Lazy Pairing Heap
PDF
Nazoki
PDF
boost tour 1.48.0 all
PDF
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
PDF
プログラミングコンテストでのデータ構造 2 ~動的木編~
PDF
Boost Tour 1.50.0 All
PDF
ウェーブレット木の世界
PDF
Proposed boost b_tree_library(ja)
PDF
Boost tour 1_40_0
ODP
これから Haskell を書くにあたって
PDF
これから Haskell を書くにあたって
KEY
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
PDF
関数型プログラミング入門 with OCaml
PDF
F#入門 ~関数プログラミングとは何か~
PDF
すごいHaskell読書会
PDF
C++0x in programming competition
PFDS 5.5 Pairing heap
PFDS 10.2.1 lists with efficient catenation
PFDS 11.2 catenable double ended queue
Lazy Pairing Heap
Nazoki
boost tour 1.48.0 all
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
Boost Tour 1.50.0 All
ウェーブレット木の世界
Proposed boost b_tree_library(ja)
Boost tour 1_40_0
これから Haskell を書くにあたって
これから Haskell を書くにあたって
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
関数型プログラミング入門 with OCaml
F#入門 ~関数プログラミングとは何か~
すごいHaskell読書会
C++0x in programming competition
Ad

PFDS 10.2.2 heaps with efficient merging

  • 1. PFDS #11 復習 10.2.2 Heaps With Efficient Merging @yuga 2012-11-08 (初版) 2012-11-10 (2版) 2012-11-30 (3版) Copyright © 2012 yuga 1
  • 2. 動機 HeapをO(1)でマージしたいよ! Copyright © 2012 yuga 2
  • 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 3
  • 4. 解決の方針 HeapをO(1)でマージしたいなら HeapをHeapで管理すればいいじゃない! 一方のHeap(BootStrapped type)の内部Heap(Primitive type)に もう一方のHeap(BootStrapped type)をそのまま入れる  BootStrapped type BootStrappedHeap  Primitive type これまでに登場したやつ BootStrappedHeap同士の大小比較はルートノードで判定する Copyright © 2012 yuga 4
  • 5. 図解: 解決の方針 絵にすると(ここでは例として Primitive type に BinomialHeap を使用) BinomialHeap の状態 BinomialHeap の状態 2 3 9 6 4 7 5 4 9 6 merge 5 7 8 BootStrappedHeap BinomialHeap Copyright © 2012 yuga 5
  • 6. 図解: 解決の方針 merge結果 2 BinomialHeap の状態 BootStrappedHeap 同士の大小比較は 3 ルートノードの値で判定 3 4 6 9 7 5 4 6 9 5 7 Copyright © 2012 yuga 6
  • 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 7
  • 8. 実装 そんなわけでこれまでに登場したHeapを使って Heapを作ります。  本に載ってるコードは、例によって実際にはコンパイルが通らない SMLコード  本文はその意図するところの説明に費やされている  これをOCamlで動くものにかえるぜ Copyright © 2012 yuga 8
  • 9. 難しいOCaml OCamlのモジュール難しい orz https://twitter.com/camloeba/status/265702576954171392 Copyright © 2012 yuga 9
  • 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 最後 functor が HEAP を返すように type t = E | H of Elem.t * PrimH.heap 型を明示したいけど書けない include ORDERED with type t := t もっと別の書き方もある?? end = struct type t = E 追記: あった => P13へ | 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 Copyright © 2012 yuga 10
  • 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 MakeH には ORDERED型のパラメタを受け取りHEAP を返すfunctorである end = struct type t = E ScheduledBinomialHeap がアサインされる | H of Elem.t * PrimH.heap 結果、MakeH により BootStrappedElem 型の要素を持つ HEAP が作られる let eq = function (* snip *) end and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem) include BootStrappedElem type heap = t let empty = E ScheduledBinomialHeap の型は let isEmpty = function (* snip *) functor (Element : ORDERED) -> HEAP with module Elem = Element end open ScheduledBinomialHeap;; module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int) Copyright © 2012 yuga 11
  • 12. 実装: メモ #2 open Ordered;; open Heap;; module BootStrappedHeap = functor (MakeH : functor (Element : ORDERED) -> HEAP with module Elem = Element) -> functor (Element : ORDERED) -> struct Element には Int がアサインされる module Elem = Element exception Empty HEAP は要素のシグネチャを Elem で持つ module rec BootStrappedElem : sig type t = E Elem.t の型は int になる | H of Elem.t * PrimH.heap PrimH は MakeH により作られる HEAP include ORDERED with type t := t end = struct BootStrappedElem と PrimH は相互依存するので rec 指定 type t = E | H of Elem.t * PrimH.heap BootStrappedElem は HEAP に格納される要素になるので、 let eq = function (* snip *) ORDERED のシグネチャを実装する end and PrimH : HEAP with module Elem := BootStrappedElem = MakeH (BootStrappedElem) include BootStrappedElem BootStrappedHeap は、BootStrappedElem 内で定義した型 t が type heap = t 自分の型 heap でもあるので、include で自分の中に展開し heap にアサイン let empty = E let isEmpty = function BootStrappedHeap が ORDERED のシグネチャを持つ (* snip *) end Int を要素として格納するよう指定 open ScheduledBinomialHeap;; module IntBootStrappedHeap : HEAP with module Elem = Int = BootStrappedHeap (ScheduledBinomialHeap) (Int) Copyright © 2012 yuga 12
  • 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 Copyright © 2012 yuga 13