Reputation: 51
I am trying to remove nodes from a Binary Search Tree. I can successfully remove any other node on the tree except for one particular case. If the targeted node has 2 children, and the left child has a right subtree, I can locate the correct replacement Node and switch the value to the targeted Node, but then the replacement node is never deleted.
Looking at the picture above, if I try to delete 17, the program will correctly navigate to 13 and replace 17 with 13, but it will not then delete the original 13 as it is supposed to.
I have attached my remove methods and those referenced within.
public Node root;
public void delete(int value){
Node node = new Node<>(value);
Node temp;
if(root == null) {
System.out.println("The tree is already empty!"); //tree is empty
return;
}
if (root.value == node.value) { //Root is target value
temp = node.left;
if(temp.right == null){
node.value = temp.value;
temp = null;
}
else{
while(temp.right != null){
temp = temp.right;
}
node.value = temp.value;
temp = null;
}
return;
}
deleteRec(root, node);
}
private void deleteRec(Node lastRoot, Node node){
Node temp;
if (lastRoot.value >= node.value){
if (lastRoot.left.value == node.value){
node = lastRoot.left;
if(node.left == null && node.right == null){ //No children
node = null;
lastRoot.left = null;
}
else if(node.left == null && node.right != null){ //Right Child
lastRoot.left = node.right;
node = null;
lastRoot.left = null;
}
else if(node.left != null && node.right == null){ //Left Child
lastRoot.left = node.left;
node = null;
}
else{ //Two Children
if(node.left.right == null){
node.value = node.left.value;
node.left = node.left.left;
node.left = null;
}
else{
node = findReplacement(node.left);
lastRoot.left.value = node.value;
node.left = null;
}
}
}
else{
deleteRec(lastRoot.left, node);
}
}
else{
if (lastRoot.right.value == node.value){
node = lastRoot.right;
if(node.left == null && node.right == null){ //No Children
node = null;
lastRoot.right = null;
}
else if(node.left == null && node.right != null){ //Right Child
lastRoot.left = node.right;
node = null;
lastRoot.right = null;
}
else if(node.left != null && node.right == null){ //Left Child
lastRoot.right = node.left;
node = null;
}
else{ //Two Children
if(node.left.right == null){
node.value = node.left.value;
node.left = node.left.left;
node.left = null;
}
else{
node = findReplacement(node.left);
lastRoot.left.value = node.value;
node.left = null;
}
}
}
else{
deleteRec(lastRoot.right, node);
}
}
}
private Node findReplacement(Node node) {
while(node.right != null){
node = node.right;
}
return node;
}
And here is my Node class:
public class Node<T> {
public int value;
public Node left;
public Node right;
public Node parent;
public Node(int value) {
this.value = value;
}
}
Upvotes: 4
Views: 503
Reputation: 9071
Consider this part of your code:
Node rep = findReplacement(node.left);
node.value = rep.value;
rep = null;
You're finding the replacement, and making rep
point to it. Then, essentially what you're doing is making rep
point to null
. This doesn't remove the node! The parent is still pointing to it!
There are several places in your code where you're doing something along these lines. The way you're expected to remove nodes from a tree in this Java implementation is by changing what parents point to. The garbage collector takes care of the other details. I hope addressing this issue helps you resolve your problem!
Upvotes: 1