Es ist tatsächlich möglich, alle Knoten in einem Binärbaum mit O (n) und O (1) Hilfsspeicherplatz zu löschen, indem ein Algorithmus basierend auf tree rotations verwendet wird.
u
/\
v C
/\
A B
Eine Rechtsdrehung dieses Baumes u und die Ergebnisse in der folgenden Baum des Knotens v über dem Knoten zieht::
einen binären Baum mit der folgenden Form gegeben
v
/\
A u
/\
B C
Man beachte, dass Eine Baumrotation kann in O (1) -Zeit und -raum erfolgen, indem einfach die Wurzel des Baums in v geändert wird, das linke Kind von u als ehemaliges rechtes Kind von v festgelegt wird und vs rechtes Kind als u festgelegt wird.
Baumrotationen sind in diesem Zusammenhang nützlich, da eine Rechtsdrehung die Höhe des linken Teilbaums des Baums immer um eins verringert. Dies ist wegen einer cleveren Beobachtung nützlich: Es ist extrem einfach, die Wurzel des Baums zu löschen, wenn es kein linkes Subchild mehr hat. Insbesondere wird, wenn der Baum wie folgt geformt:
v
\
A
Dann können wir alle Knoten im Baum löschen, indem Sie den Knoten v löschte, dann alle Knoten in dem Baum A. Löscht Dies führt zu einem sehr einfachen Algorithmus für alle Knoten im Baum zu löschen:
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.
}
}
Dieser Algorithmus eindeutig verwendet nur O (1) Stauraum, weil sie höchstens eine konstante Anzahl von Zeigern zu tun, um eine Drehung oder zu ändern, um die Wurzel und die Bedürfnisse Platz für diese Zeiger kann über alle Iterationen der Schleife wiederverwendet werden.
Darüber hinaus kann gezeigt werden, dass dieser Algorithmus auch in O (n) Zeit läuft. Intuitiv ist es möglich, dies zu sehen, indem man sich anschaut, wie oft eine gegebene Kante gedreht werden kann. Beachten Sie zunächst, dass bei jeder Ausführung einer Rechtsdrehung eine Kante, die von einem Knoten zu ihrem linken Kind führt, in eine rechte Kante konvertiert wird, die vom ehemaligen Kind zurück zu seinem Elternteil verläuft. Als nächstes beachten Sie, dass wir, sobald wir eine Rotation durchführen, die den Knoten u zum rechten Kind des Knotens v bewegt, nie wieder den Knoten u berühren werden, bis wir Knoten v und den gesamten linken Teilbaum von v gelöscht haben. Als Ergebnis können wir die Anzahl der gesamten Rotationen begrenzen, die jemals ausgeführt werden, indem wir beachten, dass jede Kante in dem Baum höchstens einmal mit ihrem Elternteil rotiert wird. Folglich gibt es höchstens O (n) -Drehungen, von denen jede O (1) -Zeit und genau n Löschungen benötigt. Dies bedeutet, dass der Algorithmus in der Zeit O (n) läuft und nur O (1) Raum verwendet. Wenn es hilft, habe ich a C++ implementation of this algorithm, zusammen mit einer viel eingehenderen Analyse des Verhaltens des Algorithmus.Es enthält auch formelle Beweise für die Richtigkeit aller Schritte des Algorithmus.
Hoffe, das hilft!
Interessanterweise holt der DSW-Algorithmus den Baum in ein Rückgrat, indem er so ziemlich den gleichen Algorithmus verwendet, den ich oben vorgeschlagen habe: rechts drehen, bis kein Kind mehr übrig ist, dann am rechten Kind wiederholen. In gewisser Weise ist meine Antwort eine optimierte Version des ersten Schrittes von DSW kombiniert mit dem Löschschritt. Danke, dass Sie den DSW-Ansatz vorgeschlagen haben! – templatetypedef
@templatetypedef Ich habe gerade Ihren Beitrag gelesen. Gut gemacht! Sieht so aus, als ob ich weniger Wörter verwende, um dieselbe Antwort zu geben. Bis abstimmen zu dir! – kasavbere