SlideShare une entreprise Scribd logo
1  sur  13
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11nekko1119
 
The Why and How of Java8 at LINE Fukuoka
The Why and How of Java8 at LINE FukuokaThe Why and How of Java8 at LINE Fukuoka
The Why and How of Java8 at LINE FukuokaYouhei Nitta
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプKohsuke Yuasa
 
C++による数値解析の並列化手法
C++による数値解析の並列化手法C++による数値解析の並列化手法
C++による数値解析の並列化手法dc1394
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門natrium11321
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 

Tendances (8)

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

Plus de 昌平 村山

PFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queuePFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queue昌平 村山
 
PFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenationPFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenation昌平 村山
 
PFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy RepresentationsPFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy Representations昌平 村山
 
PFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time DequesPFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time Deques昌平 村山
 
PFDS 5.5 Pairing heap
PFDS 5.5 Pairing heapPFDS 5.5 Pairing heap
PFDS 5.5 Pairing heap昌平 村山
 

Plus de 昌平 村山 (6)

PFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queuePFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queue
 
PFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenationPFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenation
 
PFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy RepresentationsPFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy Representations
 
PFDS chart
PFDS chartPFDS chart
PFDS chart
 
PFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time DequesPFDS 8.4.3 Real-Time Deques
PFDS 8.4.3 Real-Time Deques
 
PFDS 5.5 Pairing heap
PFDS 5.5 Pairing heapPFDS 5.5 Pairing heap
PFDS 5.5 Pairing heap
 

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