5.5 Pairing Heap

   2012/03/04 (初版)
   2012/04/13 (2版)
      @yuga
目次
•   データ構造
•   特徴
•   実装
•   解析(最悪実行時間)
•   解析(Amortized時間)
データ構造
• ヒープ規則で順序づけられた多分岐木
      – (整数で小さい順なら)親はどの子より小さい
        ※以後、これを採用して説明します


• data PairingHeap a = E | T a [PairingHeap a]
      – ただし、Heapの子に E は登場しない


Fredman, Michael L.; Sedgewick, Robert; Sleator, Daniel D.; Tarjan, Robert E. (1986),
"The pairing heap: a new form of self-adjusting heap“
http://www.lb.cs.cmu.edu/afs/cs.cmu.edu/user/sleator/www/papers/pairing-heaps.pdf
図解: データ構造
                      親
              2
                          子
      3       7   8

  6       4       9

          5
特徴
• 実装が単純で簡単
• 実用上すぐれた性能をもつ

• 正確なamortized時間を解析することが困難
実装: Heapの関数
テキストより:

•   findMin
•   merge
•   insert
•   deleteMin
実装: findMin
• 木はヒープ規則で順序づけられているので、
  findMinの実装は自明
• 単にheapの最上位要素を返す


        findMin (T x _) = x
実装: merge
• merge関数はふたつの木のルート要素を比較して、
  小さい方を結果のルートに残し、大きい方とその部
  分木をルートの部分木として追加する

   merge   h E = h
   merge   E h = h
   merge   h1@(T x hs1) h2@(T y hs2)
       |   x < y     = T x (h2:hs1)
       |   otherwise = T y (h1:hs2)
図解: merge
            merge       3           2

                    6       4   7       8

                            5           9




    3         >     2                                   2

6       4           7       8                   3       7   8

        5                   9
                                            6       4       9

                                                    5
実装: insert
• insert関数は追加する要素に対して新しい木を作り、
  追加先の木にマージする。


   insert x h = merge (T x []) h
図解: insert
insert   5   E           5

insert   4   5           4

                         5

insert   3   4           3

             5           4

                         5

insert   6   3           3

             4       6       4

             5               5
実装: deleteMin
• ルートを取り除き、部分木をマージする。


   mergePairs [] = E
   mergePairs [h] = h
   mergePairs (h1:h2:hs) =
       merge (merge h1 h2) mergePairs hs

   deleteMin (T x hs) = mergePairs hs
図解: deleteMin
                                       ① 削除




                                                ③ Combining
            merge   merge     merge           merge
② Pairing

                                      merge

                            merge
図解: deleteMin

            2                     3

    3       7   8         8   7       6   4

6       4       9         9               5

        5
実装: 二分木への変換
• 二分木のデータ構造
    data BinTree a = E'
                   | T' (BinTree a) a (BinTree a)




• 変換
toBinary :: PairingHeap a -> BinTree a
toBinary E = E'
toBinary (T x hs) = T' (tree hs) x E'
    where
      tree [] = E'
      tree ((T x hs1):hs2) = T' (tree hs1) x (tree hs2)
図解: half-ordered binary tree へ変換

                                           2
               2
                                   3               E
       3       7   8

                           6                   7
   6       4       9

           5           E           4   E                   8


                                                               E
                           5           E           9


                       E       E           E           E
解析: 最悪実行時間
• O(1)
  – findMin、insert、mergeの各関数は、最悪時間
    O(1)で実行できる
     • 実装をみればすぐわかる


• O(n)
  – deleteMin関数は最悪O(n)時間を要する
     • ルートの子に、他のすべてのノードがあるような場合、
       そこから最少のノードを見つけるのにO(n)
解析: Amortized時間
どうする?

• 適当な構造を仮定してみる
 – Scrambled Pairing


• 既存のデータ構造との類似点に注目する
 – Splay木
仮定: Scrambled Pairing (1)
以下の構造で、insert、deleteMinを繰り返す

                   insert




       最大の木に
                             Root削除
       combining



                   pairing
仮定: Scrambled Pairing (2)
• ポテンシャル関数
 – 木のノード数をn、各ノードが持つ子の数をd
 – 木のポテンシャルは、各ノードのポテンシャルの合計
 – 各ノードのポテンシャル
             1 − min 𝑑,   𝑛

• 解析: 実コスト
 – ルートを削除したとき、k個の木が残ると仮定する
 – コストをPairing時のmerge回数とする
 ⇒ 𝑘/2 + 1
仮定: Scrambled Pairing (3)
• 解析: ポテンシャルの変化
  – ルートの削除で高々 2 𝑛 増加
    • 削除されたルートのポテンシャル: 1 − √𝑛 から 0
    • 少なくとも √𝑛 個の子を持つノードごとに 1 増加
  – Pairing時のmergeごとに 1 減少
    • ただし、 すでに √𝑛 個の子をもつノードを除く
      (そういうノードは高々 𝑛存在する)
  ⇒ 𝑘/2 − √𝑛

                          𝑘
⇒ 𝑘/2 + 1 + 2 𝑛 + ( 𝑛 −       ) = 𝑂(√𝑛)
                          2
類似点: Splay木
• Pairing Heapでの構造変化
 – Pairing
 – Paring & Combining


• Splay木での構造変化
 – Splaying
図解: Pairingによる構造変化                      X
                                Y
                X < Y の場合

        X                               C
                            B       A
            Y
                                        Y
A
                                X
    B       C
                X > Y の場合
                                        C
                            A       B
図解: Pairing & Combiningによる構造変化




    Pairing

               Combining
図解: Splayingによる構造変化


           トップダウン
            Splaying
            (zig-zig)
類似点: Splay木
Pairing HeapのParing & CombiningはSplay木の
Splayingと同じ効果がある。
解析: Amortized時間
• Amortized時間
  – Splay木との類似点から、insert関数、merge関数、
    deleteMin関数がどれもすべてO(log n)の
    amortized時間で実行するといえる

  – insert関数とmerge関数は実際にはO(1)の
    amortized 時間で実行すると推測されているが、
    しかし誰もこの主張を証明したり反証した者はい
    ない
解析: Amortized時間
Pairing HeapのParing & CombiningはSplay木の
Splayingと同じ効果がある。




Splay木のポテンシャル関数を使おう。
解析: ポテンシャル関数
• 定義
 – Paring Heapを2分木に変換した木
   • ノード数:
     n
   • ノード x のサイズ:
     #x = x を根とする部分木のノード数(xを含む)
   • ノード x のポテンシャル:
     φ(x) = log(#x)
   • 木 t 全体のポテンシャル:
     Φ(t) = その木すべてのノードのポテンシャルの合計
解析: ポテンシャル関数
• 定義(続き)
 – 複数の木の集合
   • 木を持たない場合は 0
   • 常にnon-negative
解析: findMin
• O(1)
  – ポテンシャルの変化がないため
解析: insert / merge
• O(log n)
  – 高々 log(n) + 1のポテンシャル増加による
    • ノード数の少ない方の木のルート:
      高々log(n)増加
    • ノード数の多い方の木のルート:
      高々1増加
       – より多い方のルートが配下に組み入れられる最大のノード数
         を持った相手は、自分と同じだけの数を持った相手)
                     𝑛           2
         log 𝑛 − log   = log 𝑛 ×   = log 2 = 1
                     2           𝑛
解析: deleteMin
• O(log n)
  – 実コスト
    •   1 + mergeの実行回数
  – ポテンシャルの変化
    •   ルートの削除
        –   ポテンシャルlog(n)の減少   ①
    •   Pairing
    •   Combining
  – 全体
解析: Pairing (1)
部分木Cが空でない場合:
    – Pairingでmergeを1回実行したときのポテンシャルの増加( 部分)

     ϕ 𝑥′ − 𝜙 𝑦
      = log #𝑎 + #𝑏 + 1 − log(#𝑏 + #𝑐 + 1)            ②

       x       merge


a                                            y'
                    y            x'
           b                                      c
                c            a        b
解析: Pairing (2)
– mergeによるポテンシャル増加の上界
 𝑥, 𝑦 > 0 , 𝑥 + 𝑦 ≤ 1 となる、すべての x, y について
                    log 𝑥 + log 𝑦 ≤ −2

 したがって、
 log #𝑎 + #𝑏 + 1 + log #𝑐 − 2 log #𝑎 + #𝑏 + #𝑐 + 2
          #𝑎 + #𝑏 + 1                 #𝑐
 = log                   + log                          ③
        #𝑎 + #𝑏 + #𝑐 + 2        #𝑎 + #𝑏 + #𝑐 + 2
 ≤ −2

 log #𝑐 ≤ log(#𝑏 + #𝑐 + 1) だから、②と③より、

     log #𝑎 + #𝑏 + 1 − log #𝑏 + #𝑐 + 1
              < 2 log #𝑎 + #𝑏 + #𝑐 + 2 − 2 log #𝑐 − 2
              = 2 log #𝑥 − 2 log #𝑐 − 2                 ④
解析: Pairing (3)
部分木Cが空の場合:
 – Paringでmergeを1回実行したときのポテンシャルの増加

  ϕ 𝑥′ − 𝜙 𝑦
      = log #𝑎 + #𝑏 + 1 − log #𝑏 + 1
      ≤ 2log #𝑎 + #𝑏 + 2
      = 2 log #𝑥                                ⑤

       x       merge

   a                                   y'
                    y        x'
           b                                c
                c        a        b
解析: Pairing (4)
• Pairing全体のポテンシャル増加の上界
 𝑥1, 𝑥2 , 𝑥3 , 𝑥4 , … , 𝑥2𝑘−1 , 𝑥2𝑘 をParingでmergeする部分木のルート集合と
 する。

    𝑘−1

          2 log #𝑥2𝑖−1 − 2 log #𝑥2𝑖+1 − 2 + 2 log 𝑥2𝑘−1     ⑥
    𝑖=1                 ④                         ⑤


           𝑥1     𝑥2      𝑥3      𝑥4      𝑥2𝑘−1       𝑥2𝑘
解析: Pairing (5)
     𝑘−1

⑥=         2 log #𝑥2𝑖−1 − 2 log #𝑥2𝑖+1   + 2 log 𝑥2𝑘−1 − 2 𝑘 − 1
     𝑖=1


= 2 log #𝑥1 − 2 𝑘 − 1

= 2 log 𝑛 − 2(𝑘 − 1)                                               ⑦
解析: Combining
 𝜙 𝑥′ + 𝜙 𝑦′   − 𝜙 𝑥 + 𝜙 𝑦
= log 𝑛 − 1 + log 𝑛 − log 𝑛 − log 1
= log 𝑛 − 1                                     ⑧


                                           y’
        x                             x’
    z             y             z
解析: deleteMin全体
実コスト + ①ルート除去 + ⑦𝑃𝑎𝑟𝑖𝑛𝑔 + ⑧𝐶𝑜𝑚𝑏𝑖𝑛𝑔

= 2𝑘 + 1 + − log 𝑛   + 2 log 𝑛 − 2(𝑘 − 1) + log 𝑛 − 1
= log 𝑛 + log 𝑛 − 1 + 3
≤ 2log 𝑛 + 3 = 𝑂 log 𝑛
参考文献
•   Chris Okasaki, “5.5 Paring Heaps”, Purely Functional Data Structures, Cambridge University
    Press (1999)
•   Wikipedia, “Paring heap”, on 29 January 2012 at 15:45
    http://en.wikipedia.org/wiki/Pairing_heap
•   Fredman, Michael L.; Sedgewick, Robert; Sleator, Daniel D.; Tarjan, Robert E.,
    "The pairing heap: a new form of self-adjusting heap“, 1986
    http://www.lb.cs.cmu.edu/afs/cs.cmu.edu/user/sleator/www/papers/pairing-heaps.pdf

PFDS 5.5 Pairing heap

  • 1.
    5.5 Pairing Heap 2012/03/04 (初版) 2012/04/13 (2版) @yuga
  • 2.
    目次 • データ構造 • 特徴 • 実装 • 解析(最悪実行時間) • 解析(Amortized時間)
  • 3.
    データ構造 • ヒープ規則で順序づけられた多分岐木 – (整数で小さい順なら)親はどの子より小さい ※以後、これを採用して説明します • data PairingHeap a = E | T a [PairingHeap a] – ただし、Heapの子に E は登場しない Fredman, Michael L.; Sedgewick, Robert; Sleator, Daniel D.; Tarjan, Robert E. (1986), "The pairing heap: a new form of self-adjusting heap“ http://www.lb.cs.cmu.edu/afs/cs.cmu.edu/user/sleator/www/papers/pairing-heaps.pdf
  • 4.
    図解: データ構造 親 2 子 3 7 8 6 4 9 5
  • 5.
    特徴 • 実装が単純で簡単 • 実用上すぐれた性能をもつ •正確なamortized時間を解析することが困難
  • 6.
    実装: Heapの関数 テキストより: • findMin • merge • insert • deleteMin
  • 7.
    実装: findMin • 木はヒープ規則で順序づけられているので、 findMinの実装は自明 • 単にheapの最上位要素を返す findMin (T x _) = x
  • 8.
    実装: merge • merge関数はふたつの木のルート要素を比較して、 小さい方を結果のルートに残し、大きい方とその部 分木をルートの部分木として追加する merge h E = h merge E h = h merge h1@(T x hs1) h2@(T y hs2) | x < y = T x (h2:hs1) | otherwise = T y (h1:hs2)
  • 9.
    図解: merge merge 3 2 6 4 7 8 5 9 3 > 2 2 6 4 7 8 3 7 8 5 9 6 4 9 5
  • 10.
    実装: insert • insert関数は追加する要素に対して新しい木を作り、 追加先の木にマージする。 insert x h = merge (T x []) h
  • 11.
    図解: insert insert 5 E 5 insert 4 5 4 5 insert 3 4 3 5 4 5 insert 6 3 3 4 6 4 5 5
  • 12.
    実装: deleteMin • ルートを取り除き、部分木をマージする。 mergePairs [] = E mergePairs [h] = h mergePairs (h1:h2:hs) = merge (merge h1 h2) mergePairs hs deleteMin (T x hs) = mergePairs hs
  • 13.
    図解: deleteMin ① 削除 ③ Combining merge merge merge merge ② Pairing merge merge
  • 14.
    図解: deleteMin 2 3 3 7 8 8 7 6 4 6 4 9 9 5 5
  • 15.
    実装: 二分木への変換 • 二分木のデータ構造 data BinTree a = E' | T' (BinTree a) a (BinTree a) • 変換 toBinary :: PairingHeap a -> BinTree a toBinary E = E' toBinary (T x hs) = T' (tree hs) x E' where tree [] = E' tree ((T x hs1):hs2) = T' (tree hs1) x (tree hs2)
  • 16.
    図解: half-ordered binarytree へ変換 2 2 3 E 3 7 8 6 7 6 4 9 5 E 4 E 8 E 5 E 9 E E E E
  • 17.
    解析: 最悪実行時間 • O(1) – findMin、insert、mergeの各関数は、最悪時間 O(1)で実行できる • 実装をみればすぐわかる • O(n) – deleteMin関数は最悪O(n)時間を要する • ルートの子に、他のすべてのノードがあるような場合、 そこから最少のノードを見つけるのにO(n)
  • 18.
    解析: Amortized時間 どうする? • 適当な構造を仮定してみる – Scrambled Pairing • 既存のデータ構造との類似点に注目する – Splay木
  • 19.
    仮定: Scrambled Pairing(1) 以下の構造で、insert、deleteMinを繰り返す insert 最大の木に Root削除 combining pairing
  • 20.
    仮定: Scrambled Pairing(2) • ポテンシャル関数 – 木のノード数をn、各ノードが持つ子の数をd – 木のポテンシャルは、各ノードのポテンシャルの合計 – 各ノードのポテンシャル 1 − min 𝑑, 𝑛 • 解析: 実コスト – ルートを削除したとき、k個の木が残ると仮定する – コストをPairing時のmerge回数とする ⇒ 𝑘/2 + 1
  • 21.
    仮定: Scrambled Pairing(3) • 解析: ポテンシャルの変化 – ルートの削除で高々 2 𝑛 増加 • 削除されたルートのポテンシャル: 1 − √𝑛 から 0 • 少なくとも √𝑛 個の子を持つノードごとに 1 増加 – Pairing時のmergeごとに 1 減少 • ただし、 すでに √𝑛 個の子をもつノードを除く (そういうノードは高々 𝑛存在する) ⇒ 𝑘/2 − √𝑛 𝑘 ⇒ 𝑘/2 + 1 + 2 𝑛 + ( 𝑛 − ) = 𝑂(√𝑛) 2
  • 22.
    類似点: Splay木 • PairingHeapでの構造変化 – Pairing – Paring & Combining • Splay木での構造変化 – Splaying
  • 23.
    図解: Pairingによる構造変化 X Y X < Y の場合 X C B A Y Y A X B C X > Y の場合 C A B
  • 24.
    図解: Pairing &Combiningによる構造変化 Pairing Combining
  • 25.
    図解: Splayingによる構造変化 トップダウン Splaying (zig-zig)
  • 26.
    類似点: Splay木 Pairing HeapのParing& CombiningはSplay木の Splayingと同じ効果がある。
  • 27.
    解析: Amortized時間 • Amortized時間 – Splay木との類似点から、insert関数、merge関数、 deleteMin関数がどれもすべてO(log n)の amortized時間で実行するといえる – insert関数とmerge関数は実際にはO(1)の amortized 時間で実行すると推測されているが、 しかし誰もこの主張を証明したり反証した者はい ない
  • 28.
    解析: Amortized時間 Pairing HeapのParing& CombiningはSplay木の Splayingと同じ効果がある。 Splay木のポテンシャル関数を使おう。
  • 29.
    解析: ポテンシャル関数 • 定義 – Paring Heapを2分木に変換した木 • ノード数: n • ノード x のサイズ: #x = x を根とする部分木のノード数(xを含む) • ノード x のポテンシャル: φ(x) = log(#x) • 木 t 全体のポテンシャル: Φ(t) = その木すべてのノードのポテンシャルの合計
  • 30.
    解析: ポテンシャル関数 • 定義(続き) – 複数の木の集合 • 木を持たない場合は 0 • 常にnon-negative
  • 31.
    解析: findMin • O(1) – ポテンシャルの変化がないため
  • 32.
    解析: insert /merge • O(log n) – 高々 log(n) + 1のポテンシャル増加による • ノード数の少ない方の木のルート: 高々log(n)増加 • ノード数の多い方の木のルート: 高々1増加 – より多い方のルートが配下に組み入れられる最大のノード数 を持った相手は、自分と同じだけの数を持った相手) 𝑛 2 log 𝑛 − log = log 𝑛 × = log 2 = 1 2 𝑛
  • 33.
    解析: deleteMin • O(logn) – 実コスト • 1 + mergeの実行回数 – ポテンシャルの変化 • ルートの削除 – ポテンシャルlog(n)の減少 ① • Pairing • Combining – 全体
  • 34.
    解析: Pairing (1) 部分木Cが空でない場合: – Pairingでmergeを1回実行したときのポテンシャルの増加( 部分) ϕ 𝑥′ − 𝜙 𝑦 = log #𝑎 + #𝑏 + 1 − log(#𝑏 + #𝑐 + 1) ② x merge a y' y x' b c c a b
  • 35.
    解析: Pairing (2) –mergeによるポテンシャル増加の上界 𝑥, 𝑦 > 0 , 𝑥 + 𝑦 ≤ 1 となる、すべての x, y について log 𝑥 + log 𝑦 ≤ −2 したがって、 log #𝑎 + #𝑏 + 1 + log #𝑐 − 2 log #𝑎 + #𝑏 + #𝑐 + 2 #𝑎 + #𝑏 + 1 #𝑐 = log + log ③ #𝑎 + #𝑏 + #𝑐 + 2 #𝑎 + #𝑏 + #𝑐 + 2 ≤ −2 log #𝑐 ≤ log(#𝑏 + #𝑐 + 1) だから、②と③より、 log #𝑎 + #𝑏 + 1 − log #𝑏 + #𝑐 + 1 < 2 log #𝑎 + #𝑏 + #𝑐 + 2 − 2 log #𝑐 − 2 = 2 log #𝑥 − 2 log #𝑐 − 2 ④
  • 36.
    解析: Pairing (3) 部分木Cが空の場合: – Paringでmergeを1回実行したときのポテンシャルの増加 ϕ 𝑥′ − 𝜙 𝑦 = log #𝑎 + #𝑏 + 1 − log #𝑏 + 1 ≤ 2log #𝑎 + #𝑏 + 2 = 2 log #𝑥 ⑤ x merge a y' y x' b c c a b
  • 37.
    解析: Pairing (4) •Pairing全体のポテンシャル増加の上界 𝑥1, 𝑥2 , 𝑥3 , 𝑥4 , … , 𝑥2𝑘−1 , 𝑥2𝑘 をParingでmergeする部分木のルート集合と する。 𝑘−1 2 log #𝑥2𝑖−1 − 2 log #𝑥2𝑖+1 − 2 + 2 log 𝑥2𝑘−1 ⑥ 𝑖=1 ④ ⑤ 𝑥1 𝑥2 𝑥3 𝑥4 𝑥2𝑘−1 𝑥2𝑘
  • 38.
    解析: Pairing (5) 𝑘−1 ⑥= 2 log #𝑥2𝑖−1 − 2 log #𝑥2𝑖+1 + 2 log 𝑥2𝑘−1 − 2 𝑘 − 1 𝑖=1 = 2 log #𝑥1 − 2 𝑘 − 1 = 2 log 𝑛 − 2(𝑘 − 1) ⑦
  • 39.
    解析: Combining 𝜙𝑥′ + 𝜙 𝑦′ − 𝜙 𝑥 + 𝜙 𝑦 = log 𝑛 − 1 + log 𝑛 − log 𝑛 − log 1 = log 𝑛 − 1 ⑧ y’ x x’ z y z
  • 40.
    解析: deleteMin全体 実コスト +①ルート除去 + ⑦𝑃𝑎𝑟𝑖𝑛𝑔 + ⑧𝐶𝑜𝑚𝑏𝑖𝑛𝑔 = 2𝑘 + 1 + − log 𝑛 + 2 log 𝑛 − 2(𝑘 − 1) + log 𝑛 − 1 = log 𝑛 + log 𝑛 − 1 + 3 ≤ 2log 𝑛 + 3 = 𝑂 log 𝑛
  • 41.
    参考文献 • Chris Okasaki, “5.5 Paring Heaps”, Purely Functional Data Structures, Cambridge University Press (1999) • Wikipedia, “Paring heap”, on 29 January 2012 at 15:45 http://en.wikipedia.org/wiki/Pairing_heap • Fredman, Michael L.; Sedgewick, Robert; Sleator, Daniel D.; Tarjan, Robert E., "The pairing heap: a new form of self-adjusting heap“, 1986 http://www.lb.cs.cmu.edu/afs/cs.cmu.edu/user/sleator/www/papers/pairing-heaps.pdf