// CSE 143, Winter 2011, Marty Stepp // A SearchTree object represents a set of integer values implemented as a // binary search tree. The tree adds elements in order such that nodes on // the left have smaller values and nodes on the right have larger ones. // // Today's version adds remove and getMin methods. import java.util.*; // for NoSuchElementException public class SearchTree { private IntTreeNode overallRoot; // Constructs an empty binary tree (null root). public SearchTree() { overallRoot = null; } // Adds the given value to this tree at an appropriate place to retain // sorted BST ordering. // If the value is already found in the tree, it is not added. public void add(int value) { overallRoot = add(overallRoot, value); } // Private helper adds the value to the given part of the tree. // This method uses the "x = change(x);" pattern, where the node's // initial state is passed in, and its new state is returned out. // This helps us attach newly created nodes to the tree. private IntTreeNode add(IntTreeNode node, int value) { if (node == null) { node = new IntTreeNode(value); } else if (value < node.data) { node.left = add(node.left, value); // go left } else if (value > node.data) { node.right = add(node.right, value); // go right } // else value == node.data; duplicate; do nothing..... return node; } // Returns true if the given value is found in this tree, else false. // Precondition: The elements of the tree are in sorted BST order, // so that smaller elements are to the left and larger ones to the right. public boolean contains(int value) { return contains(overallRoot, value); } // Helper searches the given part of the tree for the given value. private boolean contains(IntTreeNode node, int value) { if (node == null) { return false; // base case } else if (value == node.data) { return true; // base case } else if (value > node.data) { // go right return contains(node.right, value); } else { // value < node.data // go left return contains(node.left, value); } } // Prints all elements of this tree in left-to-right order. public void print() { print(overallRoot); } // Recursive helper to print the given portion of the overall tree. private void print(IntTreeNode node) { // base case: null node, do nothing if (node != null) { // recursive case: non-null node, print it and its children // (works even if children are null, because then the recursive // call on the null child just fails the if test and does nothing) print(node.left); System.out.print(node.data + " "); print(node.right); } } // Removes the given value, if it is contained in the tree. // If the value is not contained in the tree, has no effect. public void remove(int value) { overallRoot = remove(overallRoot, value); } // Private method to remove the value from the given part of the tree. private IntTreeNode remove(IntTreeNode node, int value) { if (node == null) { // empty tree or value not found; nothing to do } else if (node.data < value) { // value is in my right subtree, if it is in the tree at all; go right node.right = remove(node.right, value); } else if (node.data > value) { // value is in my left subtree, if it is in the tree at all; go left node.left = remove(node.left, value); } else { // node.data == value; this node is the node to remove if (node.left == null && node.right == null) { // case 1: leaf; replace with null node = null; } else if (node.right == null) { // case 2: left child only; replace with left child node = node.left; } else if (node.left == null) { // case 3: right child only; replace with right child node = node.right; } else { // case 4: both children; replace with minimum value from right subtree int min = getMin(node.right); node.right = remove(node.right, min); node.data = min; } } return node; } // Returns the smallest value currently stored in the tree. // Throws a NoSuchElementException if the tree is empty. public int getMin() { if (overallRoot == null) { throw new NoSuchElementException(); } else { return getMin(overallRoot); } } // Helper to return the smallest value in the given part of the tree. private int getMin(IntTreeNode node) { if (node.left == null) { // no left child, so this must be the leftmost (min) node return node.data; } else { // I have a left child, so he must be smaller than me; go to the left return getMin(node.left); } } }