IA14

28
Introduction to Algorithms Chapter 14 Augmenting Data Structure

Transcript of IA14

Introduction to Algorithms Chapter 14

Augmenting Data Structure

Augmenting Data Structure

• 基本データ構造に+αなデータを持たせることによってより多くの操作を実現する例) Dynamic Order Statistics Interval Tree

14.1 Dynamic Order Statistics

• やりたいこと: 探索木でもorder statistic(9章)を求めたい

• n個の要素のi番目のorder statistic は i番目に大きな要素のこと

• (O(n)で任意のorder statistic を求めることができた)

ノードに追加する情報

• 以下の情報をノードに追加すればorder statistic が求められる

• x.size: ノードxをルートとするサブツリーに含まれるノードの数つまり x.size = x.left.size + x.right.size + 1 (葉のsizeは1とする)

Order Statisticを求める• 挿入/削除に伴うx.sizeの更新はひとまず置いといて..

• 以下のような手順でi番目の要素を取り出せる (赤く黒木を使うとO(lgn))

例• 17番目の要素を取り出す

ノードが何番目に大きいかを求める

• sizeを使えば求められる

例• key=38は何番目に大きい?

ループ不変式によるOS-Rankの正当性の確認

• 不変式: whileループ開始前にrはノードyをルートとするxのランクを示す

• ループ開始前: y = x で r = x.left.size + 1 より正しい

• ループ中: whileループの最後で y ← y.p としている.yがy.pの左の子ならy.pもy.p.right のサブツリーもxより大きいので,rはそのまま.yがy.pの右の子ならxはy.pとy.p.left のサブツリーより大きいのでその分rを増やす

• ループ終了時: y = T.root で終了.yのサブツリーとは全体の木そのもの.よってrはxのランクを表す

挿入時のsizeの更新• 赤黒木の挿入手順

1. 要素を挿入

2. バランスする用に場合によっては色を変えたり回転操作をする

• 1. のときは通過するノードのsizeを増やすだけ

• 2. のときはsizeに影響があるのは回転操作のみ.左回転のときは

挿入時のsizeの更新• 右回転時の操作は左回転のときと対称

• 1. の段階においてsizeを更新するノードはせいぜいlgNなのでそのコストはO(lgN)

• 2. の段階において,回転操作は高々2回

• よって挿入時のsize更新に伴うコストはO(lgN)

削除時のsizeの更新• sizeを変更しなければならないのは,削除するノードの親

• 親をルートまで遡って更新するが,これは O(lgN)

• また最大3回の回転が発生するものの,回転にともなうsizeの更新はO(1)でできる

• 結局削除時もO(lgN)でsizeを更新できる 

データ構造を拡張するためのステップ

1. 基本となるデータ構造を決める

2. 基本データ構造に追加する情報を決める

3. その情報がデータ構造を変形するとき(挿入・削除時)でも正しく保つことができるかどうかを確認

4. 新しい操作を追加

具体例• Step1: 赤黒木を選択

• Step2: sizeフィールドを追加

• Step3: 挿入・削除時にsizeフィールドがO(lgN)でできるか確認

• Step4: OS-SelectやOS-Rankの作成

実際は

• 実際に以上の4ステップを確認することは大変

• ただし,ある種の情報なら挿入・削除時に効率的にその情報を更新できることを証明できる

Theorem 14.1• fを赤黒木Tのn個のノードに新たに追加するフィールドだとする.ノードxについて,xのフィールドfがx,x.left,x.right のみから計算できるとき,挿入・削除に伴うfの更新はO(lgN)でおこなうこができるx.f = function(x, x.left, x.right)

証明

• 基本的な考え方は,ノードxのフィールドfを変更した場合,その変更はxの親にのみ影響するということ.x.fを変更 → x.p.fを変更 → x.p.p.fを変更→ … root.f を変更 → 終了

• 木の高さはlgNなので更新操作はO(lgN)

挿入時• 赤黒木では挿入は2つの段階からなる

• ノードxを挿入したとする

• 第一段階でx.fは定義からO(1)で計算できる.また,その後rootまでその変更は伝搬するが,それはO(lgN)

• 第二段階では回転が場合によって発生する.回転によって影響を受けるノードは2つ.第一段階同様変更はrootまで伝搬するのでO(lgN). 回転はせいぜい2回なので結局これもO(lgN)

削除時• 赤黒木では削除も二段階からなる

• ノードxを削除したとき,xが葉でなければxの子のいずれかがxの位置へ移動するが,そのときfの修正コストはO(lgN)

• 第二段階では最大3回の回転が発生するが,これもfの修正にはそれぞれO(lgN)しかかからない

14.3 Interval Tree• 赤黒木のノードがある時間区間を表すように拡張する (区間木)

• 閉区間 [t1,t2] = i とおく.このとき i.low = t1, i.high = t2 と表す.二つの区間iとi’があるとき,以下のいずれかの状況が発生する

1. iとi’はオーバラップする(重なる部分が存在する)

2. iはi’の左に位置する (i.high < i’.low)

3. iはi’の右に位置する (i’high < i.low)

オーバラップの図

Interval Tree がサポートする操作

• Interval Tree のノードxのフィールド x.int は区間を表す (x.int.low, x.int.high を持つ)

• Interval-Insert(T,x): xを挿入

• Interval-Delete(T,x): xを削除

• Interval-Search(T,i): iとオーバーラップするノードへのポインタを返す(見つからなければNIL)

Interval Tree の例

データ構造を拡張するための4ステップ

• ステップ1: 基本データ構造の決定今回は赤黒木を使用.各ノードxのx.intはインターバルを表す .xの大きさはx.int.lowで表される (従って,in-orderで赤黒木を探索すると,開始時間の早いノードから取り出される)

• ステップ2: 追加する情報の決定各ノードに max というフィールドを追加する.maxはノードxをルートとするサブツリー内で最も大きい区間の終了地点 (int.high) を表す

データ構造を拡張するための4ステップ

• ステップ3: 情報の計算方法O(lgN)での計算を保障するには,maxはノードxとその子x.left,x.rightのみから計算できなければならない.実際にその3つからのみで計算できるx.max = max(x.int.high, x.left.max, x.right.max)

データ構造を拡張するための4ステップ

• ステップ4: 新しい操作の作成

!

!

!

!

• 木の高さはlgNなので,O(lgN)

Theorem 14.2

• どんなInterval-Search(T,i) の呼び出しでも,Interval-Search(T,i)は必ずiとオーバラップするノードか,あるいはオーバラップするノードが無い場合はNILを返す

Proof

• whileループは x == T.NIL か iがオーバラップするノードが見つかったとき終了

• iがオーバラップするノードが見つかればOKなので,x == T.NIL のとき本当にオーバラップするノードが無いのかを検証する