// Represents a set of elements. When accessed, elements // will be returned in their "natural ordering". import java.util.NoSuchElementException; public class TreeIntSet implements IntSet { private TreeNode overallRoot; // Constructs an empty TreeSet public TreeIntSet() { overallRoot = null; } // Adds the given value to this TreeSet. Returns true if the set was modified // and false if the value was already contained in this set. public boolean add(int value) { if (contains(value)) { return false; } overallRoot = add(overallRoot, value); return true; } // Adds the given value to the BST starting at the given root. // Post: the tree is still a valid BST private TreeNode add(TreeNode root, int value) { if (root == null) { root = new TreeNode(value); } else if (value < root.data) { root.left = add(root.left, value); } else if (value > root.data) { root.right = add(root.right, value); } return root; } // Returns true if the value is in this set, false otherwise. public boolean contains(int value) { return contains(overallRoot, value); } // Returns true if the value is in the tree starting at the // specified root, false otherwise. private boolean contains(TreeNode root, int value) { if (root == null) { return false; } else if (value == root.data) { return true; } else if (value < root.data) { return contains(root.left, value); } else { return contains(root.right, value); } } // Returns the number of elements in this set. public int size() { return size(overallRoot); } // Returns the number of nodes in the subtree with root as its root node. private int size(TreeNode root) { if (root == null) { return 0; } else { return 1 + size(root.left) + size(root.right); } } // Returns true if there are no elements in this set, false // otherwise. public boolean isEmpty() { return size() == 0; } // Removes the given value to this TreeSet. Returns true if the set was modified // and false if the value was not contained in this set. public boolean remove(int value) { if (!contains(value)) { return false; } overallRoot = remove(overallRoot, value); return true; } // Removes the given value from the BST starting at the given root. // Post: The tree is still a valid BST private IntTreeNode remove(IntTreeNode root, int value) { if (root != null) { if (value < root.data) { root.left = remove(root.left, value); } else if (value > root.data) { root.right = remove(root.right, value); } else { // found it! // leaf node case is same as removeLeaves if (root.left == null && root.right == null) { root = null; } else if (root.right == null) { // left child only root = root.left; } else if (root.left == null) { // right child only; root = root.right; } else { // Need to find the smallest value in the right (larger values) subtree int newRootValue = getMin(root.right); root.right = remove(root.right, newRootValue); root.data = newRootValue; // morphing nodes is generally bad! (don't do this on your homework) } } } return root; } // Returns the minimum value from this set. // Throws a NoSuchElementException if the set is empty. public int getMin() { if (isEmpty()) { throw new NoSuchElementException(); } return getMinNode(overallRoot).data; } // Returns the minimum value from the tree with the given root. // Pre: root is not null private TreeNode getMinNode(TreeNode root) { if (root.left == null) { return root; } else { return getMinNode(root.left); } } // Returns a comma-separated list of the elements in this set // in sorted order. public String toString() { if (overallRoot == null) { return "[]"; } else { String contents = toString(overallRoot); return "[" + contents.substring(0, contents.length() - 2) + "]"; } } // Returns a String of the elements in the tree at the given root. private String toString(TreeNode root) { if (root == null) { return ""; } else { return toString(root.left) + root.data + ", " + toString(root.right); } } private class TreeNode { public int data; // data stored at this node public TreeNode left; // reference to left subtree public TreeNode right; // reference to right subtree // Constructs a leaf node with the given data. public TreeNode(int data) { this(data, null, null); } // Constructs a leaf or branch node with the given data and links. public TreeNode(int data, TreeNode left, TreeNode right) { this.data = data; this.left = left; this.right = right; } } }