データ構造とアルゴリズム
第八回
(2012年11月30日)
平衡木
http://www.sw.it.aoyama.ac.jp/2012/DA/lecture8.html
Martin J. Dürst
© 2008-12 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 木の各操作は二分探索木の拡張)
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 木の実装
赤黒木
(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: データ項目の総数 (具体例: 50,000)
- Lp: ページの大きさ (具体例:
1024バイト)
- Lk: キーの大きさ (具体例:
4バイト)
- Ld:
キーを抜く一項目のデータの大きさ (具体例:
240バイト)
- Lpp: ページ番号 (ポインタ)
の大きさ (具体例: 4バイト)
- αmin: 最低占有率 (普通は
0.5)
B+木: ページごとの項目数
(⌊a⌋ は a の床関数、a
以下の最大の整数)
- dmax =
⌊Lp /
(Lk +
Ld)⌋ (具体例: 4)
(葉の最大項目数)
- dmin =
⌊dmax
αmin⌋ (具体例: 2)
(葉の最低項目数)
- kmax =
⌊Lp /
(Lk +
Lpp)⌋ (具体例: 128)
(内部節の最大の子供の数)
- kmin =
⌊kmax
αmin⌋ (具体例: 64)
(内部節の最低の子供の数)
B+木のノードの数
(⌈a⌉ は a の天井関数、a
以上の最小の整数)
- Ndmax = ⌈n /
dmin⌉ (具体例: 25,000)
(葉の最大数)
- Ndmin = ⌈n /
dmax⌉ (具体例: 12,500)
(葉の最低数)
- Nkmax =
⌈Ndmax /
kmin⌉ +
⌈Ndmax /
kmin2⌉ ...
(内部節の最大の数)
(具体例: 391 + 7 + 1 = 399; B+木の高さ:
4; 節総数: 25,399)
- Nkmin =
⌈Ndmin /
kmax⌉ +
⌈Ndmin /
kmax2⌉ + ...
(内部節の最低の数)
(具体例: 98 + 1 = 99; B+木の高さ: 3; 節総数: 12,599)
まとめ
- 平衡木によって辞書の基本操作は全て O(log
n) で可能
- 二次記憶装置で B
木、B+木はデータベースなどで非常に重要