データ構造とアルゴリズム
第八回
(2010年11月26日)
平衡木
http://www.sw.it.aoyama.ac.jp/2010/DA/lecture8.html
Martin J. Dürst
© 2008-10 Martin
J. Dürst 青山学院大学
目次
- 前回の残りとまとめ
- 2-3-4 木
- 赤黒木
- AVL 木
- B 木
前回のまとめ
- 辞書はキーを使って項目の探索、挿入、削除ができる抽象データ型
- 簡単な実装では一部の操作は O(n)
時間がかかる
- 二分木の実装では操作は全て平均で O(log
n) で可能が、最悪の場合は
O(n)
- 平衡木の例: トップダウン 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 木の実装
- 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ノードとして使用
- ページごとのキーの容量を最大化
- ページごとの最低のキーの数は容量の半分程度
- キー以外のデータを一番下の層だけに配置
- それによって、内部説のキーの数、子供の数を減らし、高さを制定減に抑える
まとめ
- 平衡木によって辞書の基本操作は全て O(log
n) で可能
- 二次記憶装置で B
木はデータベースなどで非常に重要