2015-05-31 7 views
6

Sto provando a scrivere un metodo per eliminare un nodo da un albero di ricerca binario. Ecco il mio metodo per eliminare un nodo.Java: l'impostazione dell'oggetto su null all'interno di un metodo non ha alcun effetto (riutilizzo del codice)

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())); 
    } 
} 

ho controllato questo metodo su un nodo foglia, anche se dopo il debug ho scoperto che l'esecuzione di nodeToBeSelected=null avviene, il nodo non viene effettivamente cancellato. Come posso ancora cercare il valore cancellato e il programma riesce ancora a recuperarlo.

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

Ecco il mio getNode metodo()

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; 
} 

è il metodo getNode() restituendo il nodo trovato per valore? Come posso renderlo di riferimento e manipolare direttamente il nodo trovato?

risposta

5

È necessario eliminare il nodo dall'albero e non localmente nel programma.

Node<Integer> nodeToBeDeleted = getNode(deletionNodeValue); 

fornisce una copia del nodo nell'albero.

nodeToBeDeleted = null; 

imposta questa copia su null. La connessione all'albero non viene cancellata perché fa parte dell'oggetto nodo. Per eliminare la connessione che avrebbe dovuto scrivere un altro metodo per eliminare un nodo, e questo dovrebbe contenere qualcosa come

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

@NashVali Non credo che si dovrebbe essere definendo 'leftNode' e' 'rightNode' come campi public' .L'utilizzo di setter è un'opzione migliore. – CKing

+0

Sì, non dovrebbero essere pubblici. Questo codice è uno snippet di un metodo fittizio 'void deleteChild (Node nodeToBeDeleted)'. – CoronA

+0

Il metodo fittizio può ancora utilizzare setter fittizi invece di utilizzare campi pubblici fittizi. Vedi la mia risposta. – CKing

4

Quando si dice nodeToBeDeleted = null; all'interno del metodo delete, non si è realmente la causa del Node restituito dal metodo getNode per iniziare indicando un null.

Java è sempre pass-by-value. Ciò significa che non è possibile creare un riferimento passato a un punto del metodo in una nuova posizione di memoria all'interno del metodo. Allo stesso modo, non è possibile creare un riferimento restituito da un punto di chiamata del metodo a una nuova posizione di memoria all'interno di un altro metodo. (Anche se la posizione è, beh .. un null).

Come per la spiegazione di cui sopra, è quasi impossibile utilizzare il metodo getNode per ottenere il Node che si wan't da eliminare e poi fare questo punto nodo a un null in qualche altro metodo. Una soluzione rapida sarebbe quella di duplicare il codice nel metodo getNode all'interno del metodo delete. È necessario aggiungere un metodo e setRightChild in Node (anziché rendere leftChild e rightChild pubblico come proposto da altri). È quindi possibile impostare a null come segue:

nodeToBeDeleted.setLeftChild(null)

4

Quando si imposta nodeToBeDeleted a null, si imposta solo il valore della variabile locale che contiene il riferimento all'oggetto reale. L'oggetto reale non viene cancellato in alcun modo.

Con il codice che hai mostrato qui, per eliminare il nodo, dovresti trovare il suo genitore e impostare il riferimento a questo nodo (leftChild o rightChild) su null. Ciò assicurerà che l'oggetto non sia referenziato dal suo genitore, probabilmente non più visibile da alcun riferimento, e di conseguenza idoneo per la garbage collection.

Problemi correlati