// Allison Obourn // CSE 143 - lecture 21 // An IntSearchTree object represents an entire binary search tree of ints. // Class invariant: // - nodes to the left of a root have smaller values // - nodes to the right of a root have larger values // - there are no duplicates import java.util.*; public class IntSearchTree { private IntTreeNode overallRoot; // Constructs an empty binary tree. public IntSearchTree() { overallRoot = null; } // Constructs a binary tree with the given node as its root. // Note: this is hacky and just useful for testing public IntSearchTree(IntTreeNode root) { overallRoot = root; } // Prints a pre-order traversal of this tree. public void printPreorder() { printPreorder(overallRoot); System.out.println(); } // Prints a pre-order traversal of the tree starting at the specified root private void printPreorder(IntTreeNode root) { if(root != null) { System.out.print(root.data + " "); printPreorder(root.left); printPreorder(root.right); } } // Prints an in-order traversal of this tree. public void printInorder() { printInorder(overallRoot); System.out.println(); } // Prints an in-order traversal of the tree starting at the specified root private void printInorder(IntTreeNode root) { if(root != null) { printInorder(root.left); System.out.print(root.data + " "); printInorder(root.right); } } // Prints a post-order traversal of this tree. public void printPostorder() { printPostorder(overallRoot); System.out.println(); } // Prints a post-order traversal of the tree starting at the specified root private void printPostorder(IntTreeNode root) { if(root != null) { printPostorder(root.left); printPostorder(root.right); System.out.print(root.data + " "); } } // Returns true if the value is in this tree, false otherwise. public boolean contains(int value) { return contains(value, overallRoot); } // Returns true if the value is in the tree starting at the // specified root. private boolean contains(int value, IntTreeNode root) { if(root == null) { return false; } else if (root.data == value) { return true; } else if (root.data > value) { return contains(value, root.left); } else { return contains(value, root.right); } } // Adds the given value to this BST. // Post: the tree is still a valid BST public void add(int value) { overallRoot = add(value, overallRoot); } // Adds the given value to the BST starting at the given root. // Post: the tree is still a valid BST private IntTreeNode add(int value, IntTreeNode root) { if(root == null) { root = new IntTreeNode(value); } else if (root.data > value) { root.left = add(value, root.left); } else if (root.data < value) { root.right = add(value, root.right); } return root; } // Removes all nodes without children (leaves) in this tree. public void removeLeaves() { overallRoot = removeLeaves(overallRoot); } // Removes all leaf nodes in the tree with the given root. private IntTreeNode removeLeaves(IntTreeNode root) { if (root != null) { if (root.left == null && root.right == null) { root = null; } else { root.left = removeLeaves(root.left); root.right = removeLeaves(root.right); } } return root; } // Returns the minimum value from this BST. // Throws a NoSuchElementException if the tree is empty. public int getMin() { if(overallRoot == null) { throw new NoSuchElementException(); } return getMin(overallRoot); } // Returns the minimum value from the BST with the given root. // Pre: root is not null private int getMin(IntTreeNode root) { if(root.left == null) { return root.data; } else { return getMin(root.left); } } // Removes the node with the given value from this BST. public void remove(int value) { overallRoot = remove(value, overallRoot); } // Removes the node with the given value from the passed // in tree. private IntTreeNode remove(int value, IntTreeNode root) { if(root == null) { return null; } else if (root.data < value) { root.right = remove(value, root.right); } else if (root.data > value) { root.left = remove(value, root.left); } else { // found it! // leaf node case is same as removeLeaves // (not necessary to have as a separate case!) if(root.left == null && root.right == null) { return null; } else if (root.right == null) { // left child only root = root.left; } else if (root.left == null) { // right child only; root = root.right; } else { int min = getMin(root.right); root.data = min; root.right = remove(min, root.right); } } return root; } }