スケープゴート木
これの確認には、定義通り以下を確認すれば良い。
ただし、3つのサイズのうち2つを計算しておき、3つ目のサイズのみを計算することで、大規模に最適化できる。例えば挿入されたノードから順に根まで順次行うことで、スケープゴート木全体に処理を行う。親のノードを根とする部分木のサイズは、自分自身を根とする部分木のサイズと、兄弟(親が同じであるノードであり、自分自身ではないノード)の部分木のサイズと親のノードの数である1を足せば求まる。
また、ノードを挿入する際にはノードを1つずつ挿入することから以下も成り立つ。
つまり、以下の計算を繰り返せば良い。
ここで、x は現在見ているノード、x+1 はその親である。size[x]は前回のsize[x+1] を再利用すれば良いため、size(sibling)が実際に必要な唯一の関数呼び出しとなる。スケープゴートを見つけると、スケープゴートを根とする部分木を再構築し、この部分木は完全二分木となる。この再構築は、部分木のノードを、中央値を部分木のノードとするように再帰的に選択すれば、O( n )時間で実行できる。
再構築操作にはO( n )時間(部分木のサイズ)がかかるため、挿入の時間計算量は最悪の場合O( n )になる。 ただし、これらの最悪のケースは頻発しないため、挿入にかかる償却時間はO(log n )で済む。
探索手法は標準の二分探索木と変わらない。平衡二分探索木なため、最悪時間計算量はO(log n )。スプレー木は探索に最悪時間計算量がO( n )であるため、スプレー木より効率的である。他の平衡二分探索木と比較すると、ノードのメモリオーバーヘッドが少ないため、参照の局所性による速度改善が可能である。
挿入操作は、一般的な二分探索木とほとんど同じだが、スケープゴートによる平衡化の処理が追加される。
挿入する場所の探索では、挿入するノードの"深さ"も記録する。これは、根から探索で子に移動する回数を数えるだけの単純なカウンターで実装すれば、根と挿入されるノード間の辺の数を効率的に(O(log n)で)計算できる。挿入するノードが(上記で定義された)α-高さ平衡条件に反している場合、以下の再構築を行う。
再構築は、スケープゴートを根とする部分木全体を平衡化する操作である。スケープゴートは、挿入されたノードの先祖であり、α-重み平衡が満たされないノードである。再構築を必要とするとき、つまりα-高さ平衡条件に反している場合には、そのような先祖は1つ以上存在する。 それらのいずれかをスケープゴートとして部分木を再構築することでα-高さ平衡の条件が満たされた木が得られる。
スケープゴートを見つけるためには、例えば挿入するノードから根まで遡り、α-重み平衡が満たされない最初のノードを選択すれば良い。
根に戻るには、根からの探索経路を保存したO(log n )のメモリか、各ノードが持つ親ポインタを用いれば良い。
上記のスケープゴートノードが実行可能なスケープゴートであるかどうかを判断するには、そのα-重み平衡が満たされているかを確認れば良い。