2015-05-31 4 views
6

Ich versuche, eine Methode zu schreiben, um einen Knoten aus einem binären Suchbaum zu löschen. Hier ist meine Methode um einen Knoten zu löschen.Java: das Setzen von Objekt auf null innerhalb einer Methode hat keine Wirkung (Wiederverwendung von Code)

public void delete(int deletionNodeValue) { 
    Node<Integer> nodeToBeDeleted = getNode(deletionNodeValue); 
    if(nodeToBeDeleted == null) return; // No node with such value exists throw an error 
    if(isLeafNode(nodeToBeDeleted)) { 
     nodeToBeDeleted = null; 
    } else if (nodeToBeDeleted.getNumChildren() == 1) { 
     bypassNode(nodeToBeDeleted); 
    }else { 
     replace(nodeToBeDeleted, getSuccessor(nodeToBeDeleted.getValue())); 
    } 
} 

ich diese Methode auf einem Blattknoten überprüft, obwohl nach dem Debuggen ich, dass die Ausführung von nodeToBeSelected=null stattfindet, entdecken, wird der Knoten nicht gelöscht. Da ich immer noch nach dem gelöschten Wert suchen kann, kann das Programm es trotzdem abrufen.

tree.add(5); 
tree.delete(5); 
System.out.println(tree.getNode(5).getValue()); // Output : 5, should've been deleted 

Hier ist meine GetNode() -Methode

public Node<Integer> getNode(int searchValue) { 
    Node<Integer> currentNode = root; 
    while(currentNode != null) { 
     int currentNodeValue = currentNode.getValue(); 
     if(searchValue == currentNodeValue) 
      return currentNode; 
     else if(searchValue < currentNodeValue) 
      currentNode = currentNode.getLeftChild(); 
     else 
      currentNode = currentNode.getRightChild(); 
    } 

    // if no node with given value is found 
    return null; 
} 

Ist GetNode() -Methode den gefundenen Knoten durch Wert zurückgibt? Wie kann ich die Referenz zurückgeben und den gefundenen Knoten direkt manipulieren?

Antwort

5

Sie müssen den Knoten aus dem Baum löschen und nicht lokal in Ihrem Programm.

Node<Integer> nodeToBeDeleted = getNode(deletionNodeValue); 

gibt Ihnen eine Kopie des Knotens in der Struktur.

nodeToBeDeleted = null; 

setzt diese Kopie auf null. Die Verbindung zur Baumstruktur wird nicht gelöscht, da sie Teil des Knotenobjekts ist. Um die Verbindung löschen würden Sie eine andere Methode schreiben müssen, um einen Knoten zu löschen und dies sollte so etwas wie

parent.leftNode = null; // if nodeToBeDeleted == leftNode 
parent.rightNode = null; // if nodeToBeDeleted == rightNode 
+0

enthalten @NashVali Ich glaube nicht, sollten Sie 'leftNode' werden die Definition und' rightNode' als 'public' Felder .Verwenden von Setter ist eine bessere Option. – CKing

+0

Ja, sie sollten nicht öffentlich sein. Dieser Code ist ein Ausschnitt einer fiktiven Methode 'void deleteChild (Node nodeToBeDeleted)'. – CoronA

+0

Die fiktive Methode kann immer noch fiktive Setter verwenden, anstatt fiktive öffentliche Felder zu verwenden. Siehe meine Antwort. – CKing

4

Wenn Sie nodeToBeDeleted = null; innerhalb des delete Methode sagen, Sie verursachen zu einem null beginnen nicht wirklich die Node durch die getNode-Methode zurück zeigt.

Java ist immer pass-by-value. Dies bedeutet, dass Sie einen Verweis auf einen Methodenpunkt nicht auf einen neuen Speicherort in der Methode verweisen können. In ähnlicher Weise können Sie keine von einem Methodenaufrufpunkt an einen neuen Speicherort innerhalb einer anderen Methode zurückgegebene Referenz erstellen. (Auch wenn der Ort ist, naja .. eine Null).

Gemäß der obigen Erläuterung ist es fast unmöglich, die getNode Methode zu verwenden, um die Node zu erhalten, die Sie wan't zu löschen und dann diesen Knotenpunkt in einem anderen Verfahren zu einem null machen. Eine schnelle Lösung wäre, den Code in der getNode Methode innerhalb der delete Methode auch zu kopieren. Sie sollten eine setLeftChild und setRightChild Methode in Node hinzufügen (im Gegensatz zur Herstellung von leftChild und rightChild public wie von anderen vorgeschlagen). Sie können es dann auf null gesetzt, wie folgt:

nodeToBeDeleted.setLeftChild(null)

4

Wenn Sie nodeToBeDeleted auf null gesetzt, Sie nur den Wert der lokalen Variablen gesetzt, die den Verweis auf das eigentliche Objekt hält. Das eigentliche Objekt wird in keiner Weise gelöscht.

Mit dem Code, den Sie hier gezeigt haben, sollten Sie zum Löschen des Knotens dessen Eltern finden und den Verweis auf diesen Knoten (leftChild oder rightChild) auf null setzen. Dadurch wird sichergestellt, dass das Objekt nicht von seinem übergeordneten Objekt referenziert wird, das wahrscheinlich nicht mehr durch irgendeinen Verweis sichtbar ist, und folglich für eine Speicherbereinigung geeignet ist.