二分木ヒープ(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
Top Related