pfds 5.5 pairing heap
DESCRIPTION
Purely Functional Data Structures 5.5 Pairing HeapTRANSCRIPT
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
図解: データ構造
3
5
2
7 8
9 4 6
親
子
特徴
• 実装が単純で簡単
• 実用上すぐれた性能をもつ
• 正確な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
6 4
5
2
7 8
9
3
6 4
5
2
7 8
9
>
3
5
2
7 8
9 4 6
実装: insert
• insert関数は追加する要素に対して新しい木を作り、追加先の木にマージする。
insert x h = merge (T x []) h
図解: insert
insert 5 E
insert 4 5
insert 3 4
5
insert 6 3
4
5
5
4
5
3
4
5
3
6 4
5
実装: deleteMin
• ルートを取り除き、部分木をマージする。
mergePairs [] = E mergePairs [h] = h mergePairs (h1:h2:hs) = merge (merge h1 h2) mergePairs hs deleteMin (T x hs) = mergePairs hs
図解: deleteMin
merge merge merge merge
merge
merge
② Pairing
③ Combining
① 削除
図解: deleteMin
3
5
2
7 8
9 4 6 5
3
7 8
9
4 6
実装: 二分木への変換
• 二分木のデータ構造
• 変換
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)
data BinTree a = E' | T' (BinTree a) a (BinTree a)
図解: half-ordered binary tree へ変換
3
5
2
7 8
9 4 6
2
3
6
4
5
7
8
9
E
E
E E
E
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削除
pairing
最大の木に combining
仮定: 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
A
B C
X
B A
C
Y
Y
A B
C
X
X < Y の場合
X > Y の場合
図解: 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増加
– より多い方のルートが配下に組み入れられる最大のノード数を持った相手は、自分と同じだけの数を持った相手)
log 𝑛 − log𝑛
2= log 𝑛 ×
2
𝑛= log 2 = 1
解析: deleteMin
• O(log n)
– 実コスト
• 1 + mergeの実行回数
– ポテンシャルの変化
• ルートの削除 – ポテンシャルlog(n)の減少
• Pairing
• Combining
– 全体
①
解析: Pairing (1)
部分木Cが空でない場合: – Pairingでmergeを1回実行したときのポテンシャルの増加( 部分)
ϕ 𝑥′ − 𝜙 𝑦 = log #𝑎 + #𝑏 + 1 − log (#𝑏 + #𝑐 + 1)
x
y
a c
y'
c x'
a
b b
merge
②
解析: Pairing (2)
– mergeによるポテンシャル増加の上界 𝑥, 𝑦 > 0 , 𝑥 + 𝑦 ≤ 1 となる、すべての x, y について
log 𝑥 + log 𝑦 ≤ −2 したがって、 log #𝑎 + #𝑏 + 1 + log #𝑐 − 2 log #𝑎 + #𝑏 + #𝑐 + 2
= log#𝑎 + #𝑏 + 1
#𝑎 + #𝑏 + #𝑐 + 2+ log
#𝑐
#𝑎 + #𝑏 + #𝑐 + 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
y a c
y'
c x'
a
b b
merge
解析: Pairing (4)
• Pairing全体のポテンシャル増加の上界 𝑥1, 𝑥2, 𝑥3, 𝑥4, … , 𝑥2𝑘−1, 𝑥2𝑘 をParingでmergeする部分木のルート集合と
する。
2log #𝑥2𝑖−1 − 2 log #𝑥2𝑖+1 − 2
𝑘−1
𝑖=1
+ 2 log 𝑥2𝑘−1
𝑥1 𝑥2 𝑥3 𝑥4 𝑥2𝑘−1 𝑥2𝑘
⑥ ④ ⑤
解析: Pairing (5)
⑥ = 2 log #𝑥2𝑖−1 − 2 log #𝑥2𝑖+1
𝑘−1
𝑖=1
+ 2 log 𝑥2𝑘−1 − 2 𝑘 − 1
= 2 log #𝑥1 − 2 𝑘 − 1
= 2 log 𝑛 − 2(𝑘 − 1)
⑦
解析: Combining
𝜙 𝑥′ + 𝜙 𝑦′ − 𝜙 𝑥 + 𝜙 𝑦
= log 𝑛 − 1 + log 𝑛 − log 𝑛 − log 1
= log 𝑛 − 1
z
x’
y’
x
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