BST manipulation is much easier to do iteratively in C/C++ than in Java because of the possibility to get a pointer to a variable.
In Java, you need to treat differently the case where the element is found at the root
; in all other cases the node you're considering is either at the left or at the right of it's parent; so you can replace C's pointer (or reference) to pointers with the parent node and a boolean indicating at which side of the parent the current node is:
public boolean remove(E someElement) {
if (root == null) {
return false;
}
int val = someElement.compareTo(root.data);
if (val < 0) {
return remove(root, false, someElement);
} else if (val > 0) {
return remove(root, true, someElement);
} else {
root = removeNode(root);
return true;
}
}
private boolean remove(Node<E> parent, boolean right, E dataItem) {
Node<E> node = right ? parent.right : parent.left;
if (node == null) {
return false;
}
int val = dataItem.compareTo(node.data);
if (val < 0) {
return remove(node, false, dataItem);
} else if (val > 0) {
return remove(node, true, dataItem);
} else {
node = removeNode(node);
if (right) {
parent.right = node;
} else {
parent.left = node;
}
return true;
}
}
I have omitted method removeNode
for the time being, right now, we can make the second method iterative:
private boolean remove(Node<E> parent, boolean right, E dataItem) {
while (true) {
Node<E> node = right ? parent.right : parent.left;
if (node == null) {
return false;
}
int val = dataItem.compareTo(node.data);
if (val < 0) {
right = false;
} else if (val > 0) {
right = true;
} else {
node = removeNode(node);
if (right) {
parent.right = node;
} else {
parent.left = node;
}
return true;
}
parent = node;
}
}
Now the method removeNode
must remove the top node and return the new top node after removal. If either left
or right
is null
, it can just return the other node, otherwise, we must find a node to replace the topnode, and it can be either the rightmost node of the left
subtree, or the leftmode node of the right
subtree.
private Node<E> removeNode(Node<E> parent) {
if (parent.left == null) {
return parent.right;
} else if (parent.right == null) {
return parent.left;
}
boolean right = random.nextBoolean();
Node<E> node = right ? parent.right : parent.left;
Node<E> last = removeLast(node, !right);
if (last == null) {
if (right) {
node.left = parent.left;
} else {
node.right = parent.right;
}
return node;
} else {
last.left = parent.left;
last.right = parent.right;
return last;
}
}
private Node<E> removeLast(Node<E> parent, boolean right) {
Node<E> node = right ? parent.right : parent.left;
if (node == null) {
return null;
}
while (true) {
Node<E> next = right ? node.right : node.left;
if (next == null) {
break;
}
parent = node;
node = next;
}
if (right) {
parent.right = node.left;
node.left = null;
} else {
parent.left = node.right;
node.right = null;
}
return node;
}