// CSE 143, summer 2012 // An BinarySearchTree object represents an entire binary search tree of ints. // class invariant: left sub tree values are less than the root // right sub tree values are greater than the root // // Changes: we added a remove method and getMin method // implemented the Set interface // made our node class an inner class import java.util.NoSuchElementException; public class SearchTree implements Set { private IntTreeNode overallRoot; // Constructs an empty binary tree public SearchTree() { overallRoot = null; } // Constructs a binary tree with the given node as its root. public SearchTree(IntTreeNode overallRoot) { this.overallRoot = overallRoot; } // Prints all elements of this tree in left to right order. public void print() { print(overallRoot); System.out.println(); } // Prints a portion of the overall tree private void print (IntTreeNode root) { if (root != null) { // print left print(root.left); // prints data System.out.print (root.data + " "); // print right print(root.right); } } // Returns true if the overall tree contains the given target value, // false otherwise public boolean contains (int value) { return contains (overallRoot, value); } // Returns true if a portion of the overall tree contains the given // target value, false otherwise. private boolean contains (IntTreeNode node, int value) { if (node == null) { return false; } else if (node.data == value) { return true; } else if (value < node.data) { return contains (node.left, value); } else { return contains (node.right, value); } } // Adds the value to the tree such that sorted BST order is maintained public void add (int value) { overallRoot = add (overallRoot, value); } // Adds the value to the given subtree. Does not add duplicates. // A node's initial state is passed in and it modified // state is returned. This is the x = change(x) pattern and // it allows attaching new 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); } else if (value > node.data) { node.right = add (node.right, value); } return node; } // Returns the minimum value in this set. // Throws a NoSuchElementException if this set is empty. public int getMin () { if (overallRoot == null) { throw new NoSuchElementException(); } return getMin (overallRoot); } // private recursive helper for getMin private int getMin (IntTreeNode root) { if (root.left == null) { return root.data; } else { return getMin(root.left); } } // Removes the given value from this set, if it is found in this set. // If the element is not found, calling this method has no effect. public void remove (int value) { overallRoot = remove (overallRoot, value); } // private recursive helper for remove private IntTreeNode remove (IntTreeNode root, int value) { if (root == null) { return null; } else if (value < root.data) { root.left = remove (root.left, value); } else if (root.data < value) { root.right = remove (root.right, value); } else { // data == value if (root.left == null && root.right == null) { root = null; } else if (root.right == null) { root = root.left; } else if (root.left == null) { root = root.right; } else { // node with 2 children int min = getMin(root.right); root.data = min; root.right = remove (root.right, min); } } return root; } // IntTreeNode objects stores a single node of a binary tree of ints. private class IntTreeNode { public int data; // data stored at this node public IntTreeNode left; // reference to left subtree public IntTreeNode right; // reference to right subtree // Constructs a leaf node with the given data. public IntTreeNode(int data) { this(data, null, null); } // Constructs a leaf or branch node with the given data and links. public IntTreeNode(int data, IntTreeNode left, IntTreeNode right) { this.data = data; this.left = left; this.right = right; } } }