tree rotationsに基づくアルゴリズムを使用して、O(n)とO(1)の補助記憶領域を使用してバイナリツリー内のすべてのノードを削除することは本当に可能です。
u
/\
v C
/\
A B
このツリーの右回転は、次のツリー内のノードuと結果上記ノードvを引っ張る:
v
/\
A u
/\
B C
留意されたい。以下の形状のバイナリツリーを考える
uの左の子をvの前の右の子に設定し、次にvの右の子をuに設定することによって、ツリーのルートをvに変更するだけで、O(1)時間と空間でツリーの回転を行うことができます。
右回転は、ツリーの左のサブツリーの高さを常に1ずつ減らすので、このコンテキストではツリーの回転が便利です。これは、賢明な観察のために役立ちます。左の子要素がない場合、ツリーのルートを削除するのは非常に簡単です。ツリーがこのような形をしている場合は特に、:
v
\
A
その後、我々は、これは非常に単純につながるそのサブツリーA.内のすべてのノードを削除、ノードvを削除することで、ツリー内のすべてのノードを削除することができますツリー内のすべてのノードを削除するためのアルゴリズム:
while (root is not null) {
if (root has a left child) {
perform a right rotation
} else {
delete the root, and make the root's right child the new root.
}
}
それは回転を行うのか、rootと変更することで、ほとんどのポインタの一定の数を必要とするため、このアルゴリズムは明らかに、(1)ストレージスペースのみOを使用していますこれらのポインタのスペースは、ループのすべての反復にわたって再利用できます。
また、このアルゴリズムもO(n)時間で実行されることがわかります。直感的には、所定のエッジを何回回転させることができるかを見ることでこれを見ることができます。最初に、右回転が実行されるたびに、ノードからその左の子に向かうエッジが、元の子からその親に戻る右端に変換されることに注目してください。次に、ノードvをノードvの右の子に移動するローテーションを実行すると、ノードvとすべてのvの左のサブツリーが削除されるまで、ノードuに再び触れることはありません。その結果、ツリー内のすべてのエッジが親を最大で1回回転することに注目して、これまでに行われるトータルローテーションの回数を制限することができます。その結果、多くのO(n)回の回転が行われ、各回転にはO(1)時間がかかり、正確にn回の削除が行われます。これは、アルゴリズムが時間O(n)で実行され、O(1)空間のみを使用することを意味します。
私はa C++ implementation of this algorithmを持っており、アルゴリズムの動作の詳細な分析を行っています。また、アルゴリズムのすべてのステップの正当性を正式に証明しています。
希望すると便利です。
興味深いことに、DSWアルゴリズムは、私が上で提案したのとほぼ同じアルゴリズムを使用して、ツリーをバックボーンにします。左の子がなくなるまで右に回転し、次に右の子で繰り返します。だから私の答えは、DSWの最初のステップを削除ステップと組み合わせて最適化したものです。 DSWのアプローチをお寄せいただきありがとうございます! – templatetypedef
@templatetypedefあなたの投稿を読んだだけです。よくやった!私はあなたと同じ返事を与えるために少ない単語を使うように見えます。あなたに投票してください! – kasavbere