public void insert(Object next) { insert(next, root); } private void insert(Object next, SearchTreeNode node) { if (node == null) { node = new SearchTreeNode(next); } else if (node.data.compareTo(next) < 0) { insert(next, node.right); } else { // compareTo >= 0 insert(next, node.left); } }Why doesn't this work? Whenever you call a method in Java, it copies the arguments into the parameter variables. Recall that all nonprimitive variables are addresses. They are not the objects themselves. So when you call a method, it copies the addresses into another variable, in this case next and node.
Suppose root is null (i.e., the tree is empty). The private method will be called with next and null (since root is null). In the private method, the first if clause will be satisfied, and the local variable node will have the address of a new SearchTreeNode. However, the root variable of the object will not see the change, because after the private method returns, node disappears. To fix this, we have the private method return that address, and then throughout the code, we have lines of the form:
variable = change(variable);For the most part, when inserting or deleting something, most of these return values will be untouched. Most of the time, it'll be setting the variable to what it already was. The only time it makes a difference is when a change is occuring. It might seem pointless to have a lot of code equivalent to:
variable = variable;but this is necessary for the change to occur where it matters.
public void removeLeaves() { root = removeLeaves(root); } private TreeNode removeLeaves(TreeNode node) { if (node != null) { if (node.left == null && node.right == null) { node = null; } else { node.left = removeLeaves(node.left); node.right = removeLeaves(node.right); } } return node; }
public void delete(Object toDelete) { root = delete(root, toDelete); } private SearchTreeNode delete(SearchTreeNode node, Object toDelete) { if (node == null) { return null; } if (node.data.compareTo(toDelete) == 0) { if (node.left == null && node.right == null) { return null; } else if (node.left == null) { // only has right child return node.right; } else if (node.right == null) { // only has left child return node.left; } else { // has both children SearchTreeNode tmp = smallestNode(node.right); node.data = tmp.data; node.right = delete(node.right, tmp.data); } } else if (node.data.compareTo(toDelete) < 0) { node.right = delete(node.right, toDelete); } else { node.left = delete(node.left, toDelete); } return node; }
// pre: node != null private SearchTreeNode smallestNode(SearchTreeNode node) { if (node.left == null) { return node; } else { // node.left != null return smallestNode(node.left); } }