So löschen Sie alle Knoten eines Binär-Suchbaums

Ich versuche, einen Code zu schreiben, um alle Knoten eines BST zu löschen (jeder Knoten hat nur drei Attribute, links, rechts und Daten, es gibt keine übergeordneten Zeiger). Der folgende Code ist, was ich gekommen bin, es löscht nur die rechte Hälfte des Baumes und hält die linke Hälfte intakt. Wie ändere ich es so, dass auch die linke Hälfte gelöscht wird (so dass ich letztlich nur den Wurzelknoten übrig lässt, der weder linke noch rechte Teilbäume hat)?

def delete(root): global last if root: delete(root.left) delete(root.right) if not (root.left or root.right): last = root elif root.left == last: root.left = None else: root.right = None 

Und zweitens, kann jemand vorschlagen, eine iterative Ansatz als auch mit Stapeln oder anderen verwandten Datenstruktur?

    4 Solutions collect form web for “So löschen Sie alle Knoten eines Binär-Suchbaums”

    Blckknght ist richtig über Müllabfuhr, aber falls Sie eine komplexere Aufräumarbeiten machen möchten, als Ihr Beispiel vorschlägt oder warum Ihr Code nicht funktioniert hat, werde ich Ihnen eine zusätzliche Antwort geben:

    Dein Problem scheint das elif node.left == last Kontrolle zu sein.

    Ich bin mir nicht sicher, was deine last Variable benutzt wird oder was die Logik dahinter steckt.
    Aber das Problem ist, dass node.left fast nie gleich ist (man gibt nur einen Knoten der last Variablen zu, wenn beide Kinder bereits auf None , was sie nicht für einen der interessanten Knoten sind (die Kinder haben) ).

    Wenn du deinen Code node.left , wirst du das sehen, wenn node.left nicht gleich ist, nur das richtige Kind wird auf None und damit nur der rechte Teil des Teilbaums gelöscht.

    Ich weiß nicht, python, aber das sollte funktionieren:

     def delete(node): if node: # recurse: visit all nodes in the two subtrees delete(node.left) delete(node.right) # after both subtrees have been visited, set pointers of this node to None node.left = None node.right = None 

    (Ich habe die Freiheit genommen, deinen root Parameter an den node , da der Knoten, der der Funktion gegeben wird, nicht der Wurzelknoten des Baumes sein muss.)

    Wenn du beide Teilbäume löschen möchtest, gibt es keine Notwendigkeit, wiederzukehren. Setzen root.left einfach root.left und root.right zu None und lassen Sie den Müllsammler auf sie aufpassen. In der Tat, anstatt eine delete Funktion an erster Stelle zu machen, könntest du einfach nur root = None und damit fertig sein!

    Bearbeiten: Wenn du einen Cleanup-Code auf die Datenwerte ausführen musst, möchtest du vielleicht durch den Baum rekurrieren, um alle zu bekommen, wenn der GC nicht genug macht. Das Zerreißen der Links im Baum sollte nicht wirklich nötig sein, aber das mache ich auch für ein gutes Maß:

     def delete(node): if node: node.data.cleanup() # run data value cleanup code delete(node.left) # recurse delete(node.right) node.data = None # clear pointers (not really necessary) node.left = None none.right = None 

    Sie hatten auch nach einem iterativen Ansatz gefragt, den Baum zu durchqueren, was ein wenig komplizierter ist. Hier ist ein Weg zu einer Traversal mit einem deque (als Stack), um die Vorfahren zu verfolgen:

     from collections import deque def delete_iterative(node): stack = deque() last = None # start up by pushing nodes to the stack until reaching leftmost node while node: stack.append(node) node = node.left # the main loop while stack: node = stack.pop() # should we expand the right subtree? if node.right && node.right != last: # yes stack.append(node) node = node.right while node: # expand to find leftmost node in right subtree stack.append(node) node = node.left else: # no, we just came from there (or it doesn't exist) # delete node's contents node.data.cleanup() node.data = None # clear pointers (not really necessary) node.left = None node.right = None # let our parent know that it was us it just visited last = node 

    Eine iterative Post-Order-Traversal mit einem Stack könnte so aussehen:

     def is_first_visit(cur, prev): return prev is None or prev.left is cur or prev.right is cur def visit_tree(root): if root: todo = [root] previous = None while len(todo): node = todo[-1] if is_first_visit(node, previous): # add one of our children to the stack if node.left: todo.append(node.left) elif node.right: todo.append(node.right) # now set previous to ourself and continue elif previous is node.left: # we've done the left subtree, do right subtree if any if node.right: todo.append(node.right) else: # previous is either node.right (we've visited both sub-trees) # or ourself (we don't have a right subtree) do_something(node) todo.pop() previous = node 

    do_something tut was auch immer du nennen willst, um diesen Knoten zu löschen.

    Sie können es ein bisschen einfacher machen, indem Sie ein Attribut auf jeden Knoten setzen, um zu sagen, ob es do_something hat, das es noch aufgerufen hat, aber offensichtlich funktioniert das nicht so gut, wenn deine Knoten __slots__ oder was auch immer haben und du nicht willst Um den Knotentyp zu ändern, um das Flag zuzulassen.

    Ich bin mir nicht sicher, was du mit den Bedingungen nach den rekursiven Anrufen machst, aber ich denke, das sollte genug sein:

     def delete(root): if root: delete(root.left) delete(root.right) root = None 

    Wie in den Kommentaren hervorgehoben, übergibt Python keine Parameter als Referenz. In diesem Fall kannst du diese Arbeit in Python wie folgt machen:

     def delete(root): if root: delete(root.left) delete(root.right) root.left = None root.right = None Usage: delete(root) root = None 

    Wie für einen iterativen Ansatz, können Sie dies versuchen. Es ist Pseudocode, ich kenne Python nicht. Grundsätzlich machen wir eine BF-Suche.

     delete(root): make an empty queue Q Q.push(root) while not Q.empty: c = Q.popFront() Q.push(c.left, c.right) c = None 

    Auch hier wird das Root nicht standardmäßig geändert, wenn du es als Funktion nutzt, aber es löscht alle anderen Knoten. Sie können einfach den Wurzel auf None nach dem Funktionsaufruf setzen oder den Parameter entfernen und an einer globalen Root-Variablen arbeiten.

    Python ist die beste Programmiersprache der Welt.