二分木ヒープ (binary heap) - saga uaoba.cc.saga-u.ac.jp/.../pdf.2018/binaryheap.pdf(binary...
TRANSCRIPT
-
二分木ヒープ(Binary Heap)2018年度担当:只木進一(工学系研究科)
-
二分木ヒープとは
集合・リストから「最小」要素を取り出す二分木ヒープは、そのための標準的データ構造
二分木ヒープを保存するデータ構造二分木ヒープの操作のメソッド
対象となるデータクラス識別のためのlabelフィールド値を保持するvalueフィールド
2
-
二分木ヒープとは、どういう二分木かある頂点の要素𝑝𝑝のvalueは、その子𝑐𝑐の要素のvalueより大きくないp.value ≤ c.value半順序木になっている
完全二分木である最下層以外の第𝑘𝑘層には、2𝑘𝑘ー1個の頂点がある。
最下層は、左から詰めて頂点がある。3
-
半順序集合(partially ordered set)または順序集合(ordered set)
集合𝑃𝑃とその上の関係≤に対して、以下の法則が常になりたつとき、𝑃𝑃を半順序集合と呼ぶ。ここで、𝑎𝑎, 𝑏𝑏, 𝑐𝑐∈𝑃𝑃となる任意の要素とする。反射律 (reflectivity):𝑎𝑎 ≤ 𝑎𝑎推移律 (transitivity): 𝑎𝑎 ≤ 𝑏𝑏 ∧ (𝑏𝑏 ≤ 𝑐𝑐) ⇒ 𝑎𝑎 ≤ 𝑐𝑐反対照律 (antisymmetry): 𝑎𝑎 ≤ 𝑏𝑏 ∧ 𝑏𝑏 ≤ 𝑎𝑎 ⇒𝑎𝑎 = 𝑏𝑏
任意の元の組𝑎𝑎, 𝑏𝑏∈𝑃𝑃に対して𝑎𝑎 ≤ 𝑏𝑏または𝑏𝑏 ≤𝑎𝑎の何れかが必ず成り立つとき、𝑃𝑃を全順序集合(totally ordered set)と呼ぶ。
4
-
20.9
80.4
50.4
110.8
60.5
70.3
100.3
40.2
120.2
30.1
90.1
10.6
1
2 3
4 5 6 7
8 9 10 11 12
label
value位置
5
-
20.9
80.4
50.4
110.8
60.5
70.3
100.3
40.2
120.2
30.1
90.1
10.6
データの保持形式
リストで保持 0番:空(リストのインデクスが1から始まるプログラミング言語では不要)
1番:根の要素 2k番:第k層の左端の要素
6
-
親子の番号の関係
親の番号 子の番号
7
i
/ 2i
2i
i
2 1i +
-
要素の追加
リストの終端に要素を追加する木の最下層の一番右に追加、または新たな層を作って、その左端に追加
8
void add (O 𝑜𝑜){int 𝑛𝑛 = 𝐿𝐿 ;𝐿𝐿.append(𝑜𝑜);𝑛𝑛 + +;shiftUp(𝑛𝑛);//要素を正しい位置へ移動
}
-
要素の追加:シフトアップ
追加した新要素を正しい位置へ移動
位置𝑘𝑘の要素が、親の位置𝑘𝑘/2 の要素よりも小さいならば、二つの要素を入れ替える
isLess(𝑖𝑖, 𝑗𝑗) 𝑜𝑜𝑖𝑖 .𝑣𝑣𝑎𝑎𝑣𝑣𝑣𝑣𝑣𝑣 < 𝑜𝑜𝑗𝑗 .𝑣𝑣𝑎𝑎𝑣𝑣𝑣𝑣𝑣𝑣のとき真
swap(𝑖𝑖, 𝑗𝑗):要素入れ替え
9
void shiftUp(int 𝑘𝑘){if ( 𝑘𝑘 > 1 && isLess(𝑘𝑘, 𝑘𝑘/2 )){
swap(𝑘𝑘, 𝑘𝑘/2 );𝑘𝑘 = 𝑘𝑘/2 ;shiftUp(k);
}}
-
7
130.2
13
新要素を末尾に追加2
0.98
0.45
0.4110.8
60.5
70.3
100.3
40.2
120.2
30.1
90.1
10.6
1
2 3
4 5 6 7
8 9 10 11 12
10要素追加の例
-
7
70.3
13
20.9
80.4
50.4
110.8
60.5
130.2
100.3
40.2
120.2
30.1
90.1
10.6
1
2 3
4 5 6 7
8 9 10 11 12
要素入れ替え
11
-
10.6
10.6
20.9
2
12 最初から木を構築
-
30.1
10.6
20.9
10.6
30.1
20.9
13
-
40.2
10.6
30.1
20.9
20.9
10.6
30.1
40.2
Swap
14
-
20.9
10.6
30.1
40.2
50.4
15
-
20.9
10.6
30.1
40.2
50.4
60.5 Swap
50.5
10.6
16
-
20.9
60.5
30.1
40.2
50.4
10.6
70.3
Swap7
0.3
60.5
17
-
20.9
30.1
40.2
50.4
10.6
Swap
70.3
60.5
70.3
80.4
80.4
20.9
18
-
最小要素の取出し
最小要素は木の根として保存されている
最小要素を取り除き、再構築する 最小要素の取り除き:リスト中の1番が空く
最後尾の要素を取り除き、リストの1番に入れる
適切な位置へシフトダウンする
19
O poll(){O 𝑡𝑡 = 𝐿𝐿.get(1);O 𝑥𝑥 = 𝐿𝐿.removeLast();𝐿𝐿.set(1, 𝑥𝑥);shiftDown(1);return 𝑡𝑡;
}
-
要素の取出し:シフトダウン
追加した新要素を正しい位置へ移動位置𝑘𝑘の要素が、子の要素の位置2𝑘𝑘と2𝑘𝑘 + 1の小さいほうの値より大きい場合、その小さい値の子を入れ替える
20
-
要素の取出し:シフトダウン
21
void shiftDown(int 𝑘𝑘){int 𝑛𝑛 = 𝐿𝐿 ;if (2 × 𝑘𝑘 ≤ 𝑛𝑛 ){
int 𝑗𝑗 = 2 × 𝑘𝑘;if (𝑗𝑗 < 𝑛𝑛 && isLess(𝑗𝑗 + 1, 𝑗𝑗))𝑗𝑗 + +;if (isLess(𝑘𝑘, 𝑗𝑗))return;swap(𝑘𝑘, 𝑗𝑗);shiftDown(𝑗𝑗);
}}
-
70.3
20.9
80.4
50.4
110.8
60.5
130.2
100.3
40.2
120.2
30.1
90.1
10.6
Rootの取出し22
-
70.3
20.9
80.4
50.4
110.8
60.5
130.2
100.3
40.2
120.2
90.1
10.6
70.3
Rootへ移動
23
-
20.9
80.4
50.4
110.8
60.5
130.2
100.3
40.2
120.2
90.1
10.6
70.3
Swap
24
-
20.9
80.4
50.4
110.8
60.5
130.2
100.3
40.2
120.2
70.3
10.6
90.1
Swap
25
-
20.9
80.4
50.4
110.8
60.5
130.2
100.3
70.3
120.2
40.2
10.6
90.1
26
-
特定の要素の値を小さくする
その要素のインデクス𝑘𝑘shiftUpを𝑘𝑘を起点に実施
27
void reduceValue(O o){ k = o のリスト中のインデクス shiftUp(k) }
void reduceValue(O o){
k = o のリスト中のインデクス
shiftUp(k)
}
-
20.9
80.4
50.4
110.2
60.5
130.2
100.3
70.3
120.2
40.2
10.6
90.1
28 Label 11の値を0.2に
Swap
-
20.9
80.4
50.4
110.2
60.5
130.2
100.3
70.3
120.2
40.2
10.6
90.1
29 Label 11の値を0.2に
-
特定の要素の値を大きくする
その要素のインデクス𝑘𝑘shiftDownを𝑘𝑘を起点に実施
30
void raiseValue(O o){ k = o のリスト中のインデクス shiftDown(k) }
void raiseValue(O o){
k = o のリスト中のインデクス
shiftDown(k)
}
-
20.9
80.4
50.4
110.8
60.5
130.2
100.3
70.3
120.2
40.4
10.6
90.1
31 Label 4の値を0.4に
Swap
-
20.9
80.4
50.4
110.8
60.5
130.2
100.3
70.3
120.2
40.4
10.6
90.1
32 Label 4の値を0.4に
Swap
二分木ヒープ�(Binary Heap)二分木ヒープとは二分木ヒープとは、どういう二分木か半順序集合(partially ordered set)または順序集合(ordered set)スライド番号 5データの保持形式親子の番号の関係要素の追加要素の追加:シフトアップスライド番号 10スライド番号 11スライド番号 12スライド番号 13スライド番号 14スライド番号 15スライド番号 16スライド番号 17スライド番号 18最小要素の取出し要素の取出し:シフトダウン要素の取出し:シフトダウンスライド番号 22スライド番号 23スライド番号 24スライド番号 25スライド番号 26特定の要素の値を小さくするスライド番号 28スライド番号 29特定の要素の値を大きくするスライド番号 31スライド番号 32