データ構造とアルゴリズム
第九回
(2014年11月21日)
平衡木
http://www.sw.it.aoyama.ac.jp/2014/DA/lecture9.html
Martin J. Dürst
© 2009-14 Martin
J. Dürst 青山学院大学
目次
前回のまとめ
- 辞書はキーを使って項目の探索、挿入、削除ができる抽象データ型
- 簡単な実装では一部の操作は O(n)
時間がかかる
- 二分木の操作は全て平均で O(log n)
が、最悪で O(n)
- 整列と違って、乱数なだによる回復は不可能
二分木の普遍条件の緩和・強化
- 順位キューの実装では完全な順序を部分的な順序に緩和
- 探索木の場合、普遍条件の緩和又は強化を検討
トップダウン 2-3-4 木
(top-down 2-3-4 tree)
- 各ノードの子数は 2、3 または 4
- 子数が k の場合、ノードに k-1
のキーとデータ項目を保持
(子数が全て 2 の場合、二分探索木と同等)
- ノード内のデータ項目のキーは部分木の分岐点
- 木の高さは一定
- 最下層には子がない
(実装上、全部同一の空のノード)
2-3-4 木での探索
- 根から開始
- 現在の頂点で探索キーが発見された場合、対応するデータ項目を返す
- 現在の頂点のキーによって、部分木を選択、再帰的に探索
(2-3-4 木の各操作は二分探索木の拡張)
2-3-4 木での挿入
- 基本動作: 最下層まで探索、キーとデータを挿入
- 最下層の頂点に既に三つの項目がある場合、頂点を分割
- 分割によって、一つ上の層に分岐点を挿入
- 挿入が根まで連鎖する可能性がある
- それを防ぐために、子数が4のノードは予め
(下向く探索のとき) 分割
- このような 2-3-4 木をトップダウン 2-3-4 木と呼ぶ
2-3-4 木での削除
- 二分探索木と同様、挿入より複雑
- 削除したい項目を発見 (探索参照)
- 削除したい項目が最下層にない場合、交換できる最下層の項目と交換
- 最下層の項目を削除
- 項目のない頂点ができたら、隣接の頂点から項目を移動
- 移動で対応できないとき、合併
- 合併で対応できないとき、上位層で対応
- 最上位層で対応できないとき、層の数を削減
2-3-4 木の効率
- 高さ h の 2-3-4 木の最大データ項目数: n = 4h-1
- 高さ h の 2-3-4 木の最低データ項目数: 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, 0, 1) を内部節に保持、更新
- 高さが 1.44 log2 n
に限定
- 検索は赤黒木より少し速い
- 挿入・削除は赤黒木より少し遅い
二次記憶装置
(secondary storage)
- 内部メモリは
- ワード単位でアクセス
(現在のマシンで 32ビットや64ビット)
- アクセスは非常に速い (ナノ秒単位)
- 二次記憶装置 (HD, SSD など) は
- 一気に大量のデータにアクセス
(1ページ、512バイト~4096バイトなど)
- アクセスは非常に遅い (ミリ秒単位)
(テープなどは線形アクセス限定のため論外)
B 木
(B-tree)
- 2-3-4 木の変形
- 一つのページは一つの頂点
- ページごとのキーの容量を最大化
- ページごとの最低のキーの数は容量の半分程度
B 木のページ
|
|
部分木参照 |
キー |
データ |
部分木参照 |
キー |
データ |
部分木参照 |
... |
... |
... |
キー |
データ |
部分木参照 |
|
|
B+木
- キー以外のデータを最下層だけに配置
- 内部節のキーの数、子供の数を増加
- 木の高さを削減
理由:
- 実用的な利用の場合、キーの大きさがデータの大きよりかなり小さい
- データへのアクセスは木の高さに比例
B+木の内部ページ
|
部分木参照 |
キー |
部分木参照 |
キー |
部分木参照 |
キー |
部分木参照 |
キー |
部分木参照 |
キー |
部分木参照 |
キー |
部分木参照 |
... |
... |
キー |
部分木参照 |
|
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)
まとめ
- 2-3-4 分木と B(+)木では
2分木の次数が増加が、高さが一定
- 赤黒木や AVL木では部分木の高さの一定の制限
- 平衡木によって辞書の基本操作は全て O(log
n)
- 二次記憶装置で B
木、B+木はファイルシステムやデータベースなどで非常に重要