データ構造とアルゴリズム
第八回
(2011年12月2日)
平衡木
http://www.sw.it.aoyama.ac.jp/2011/DA/lecture8.html
Martin J. Dürst
© 2008-11 Martin
J. Dürst 青山学院大学
目次
- 前回のまとめ
- 2-3-4 木
- 赤黒木
- AVL 木
- B 木
前回のまとめ
- 辞書はキーを使って項目の探索、挿入、削除ができる抽象データ型
- 簡単な実装では一部の操作は O(n)
時間がかかる
- 二分木の実装では操作は全て平均で O(log
n) で可能が、最悪の場合は
O(n)
- 平衡木の例: トップダウン 2-3-4 木
トップダウン 2-3-4 木
(top-down 2-3-4 tree)
- 各ノードの子数は 2、3 または 4
- 子数が k の場合、ノードに k-1
のキーとデータ項目を保持
- ノード内のデータ項目のキーは部分木の分岐点
- 木の高さは一定
- 一番下の層には子がない
(実装上、全部同一の空のノード)
2-3-4 木での探索
- 根から開始
- 現在の頂点で探索のキーが発見される場合、それに対応するデータ項目を返す
- 現在の頂点のキーによって、部分木を選択、再帰的に探索
2-3-4 木での挿入
- 基本動作: 最下層まで探索、キーとデータを挿入
- 最下位の頂点に既に三つの項目がある場合、分割が必要
- 分割によって、一つ上の層に分岐点の挿入が必要
- 挿入が根まで連鎖する可能性がある
- それを防ぐために、子数が4のノードは予め
(下向く探索のとき) 分割
- このような 2-3-4 木をトップダウン 2-3-4 木と呼ぶ
2-3-4 木での削除
- 二分探索木と同様、挿入より複雑
- 削除したい項目を発見 (探索参照)
- 削除したい項目が最下層にない場合、交換できる最下層の項目と交換
- 最下層の項目を削除
- 項目のないノードができたら、連節ノードから項目を移動
- 移動で対応できないとき、合併
- 合併で対応できないなら上位層で対応
2-3-4 木の効率
- 2-3-4 木の高さ h の最大のデータ項目の数: n = 4h-1
- 2-3-4 木の高さ h の最低のデータ項目の数: n = 2h-1
- よって、木の高さが O(log
n)
- 各操作に必要な時間は木の高さに比例するので O(log n)
2-3-4 木の実装
- Ruby での実装: 8234tree.rb
- 2-3-4 木の実装は一般的に難しいとされている
- そのため、他の平衡木が提案されている
赤黒木
(red-black-tree)
- 2-3-4 木の二分木での実装方法として定義可能
- 元の木の辺は黒
- 3子や4子のノードは複数ノードに分割、その内部の辺は赤
- 二つの赤の辺は連続不可能
- 普遍条件が崩されているとき、「回転」が必要な時がある
- 黒の辺だけを数えると木の高さが一定
- 葉の最大の深さは最小の深さの二倍以内
AVL 木
(AVL-tree)
- Adelson-Velskii と Landis (Адельсон-Вельский と
Ландис) が 1962 年に提案
- 最古の平衡木 (二分木)
- 制約 (普遍条件): どの頂点 (ノード)
でも、左と右の部分木の高さの差は 1 以下
- 部分木の高さの差を内部説に保持、更新
- 高さが 1.44 log2 n
に限定
- 検索は赤黒木より少し速い
- 挿入・削除は赤黒木より少し遅い
二次記憶装置
(secondary storage)
- 内部メモリは
- ワード単位でアクセス
(現在のマシンで 32ビットや64ビットなど)
- アクセスは非常に速い (ナノ秒単位)
- 二次記憶装置 (ハードディスクなど) は
- 一気に沢山のデータにアクセス
(1ページ、512バイト~4096バイトなど)
- アクセスは非常に遅い (ミリ秒単位)
(テープなどは線形アクセス限定のため論外)
B 木
(B-tree)
- 2-3-4 木の変形と考えられる
- 1ページを1ノードとして使用
- ページごとのキーの容量を最大化
- ページごとの最低のキーの数は容量の半分程度
- B+木ではキー以外のデータを一番下の層だけに配置
- それによって、内部節のキーの数、子供の数を増やし、高さを最低限に抑える
B+木関連の変数の定義
- n: データ項目の総数
- Lp: ページの大きさ
- Lk: キーの大きさ
- Ld: (一項目の) データの大きさ
(キーを抜く)
- Lpp: ページ番号 (ポインタ)
の大きさ
- αmin: 最低占有率 (普通は
0.5)
B+木: ページごとの項目数
(以下、整数に丸める部分は省略)
- dmax =
Lp / (Lk
+ Ld)
(葉の最大項目数)
- dmin =
dmax
αmin
(葉の最低項目数)
- kmax =
Lp / (Lk
+ Lpp)
(内部節の最大の子供の数)
- kmin =
kmax
αmin
(内部節の最低の子供の数)
B+木のノードの数
- Ndmax = n /
dmin
(葉の最大数)
- Ndmin = n /
dmax
(葉の最低数)
- Nkmax =
Ndmax / kmin
+ Ndmax /
kmin2+
...
(内部節の最大の数)
- Nkmin = Ndmin
/ kmax +
Ndmin /
kmax2 + ...
(内部節の最低の数)
まとめ
- 平衡木によって辞書の基本操作は全て O(log
n) で可能
- 二次記憶装置で B
木、B+木はデータベースなどで非常に重要