/** * A non-balancing binary search tree implementation. */ public class BinarySearchTree> { private BinaryTree root; public BinarySearchTree() { root = new BinaryTree(); // empty tree } public BinaryTree getRoot() { return root; } // Return either the "highest" node with the given value, or // the node to which the value should be added as a child private BinaryTree locate(BinaryTree curNode, T value) { T curValue = curNode.value(); if (curValue.equals(value)) { return curNode; } BinaryTree child; // look left if less-than, right if greater-than if (curValue.compareTo(value) < 0) { child = curNode.right(); } else { child = curNode.left(); } if (child.isEmpty()) { // value not in tree, return this node return curNode; } else { // arrived at another subtree node, recurse return locate(child, value); } } public boolean contains(T value) { if (root.isEmpty()) { return false; } BinaryTree node = locate(root, value); return node.value().equals(value); } public T get(T value) { if (root.isEmpty()) { return null; } BinaryTree node = locate(root, value); if (node.value().equals(value)) { return node.value(); } else { return null; } } // get the largest value not greater than root in the tree private BinaryTree predecessor(BinaryTree root) { BinaryTree result = root.left(); while (!result.right().isEmpty()) { result = result.right(); } return result; } // add a (possibly duplicate) value to the BST public void add(T newValue) { BinaryTree newNode = new BinaryTree(newValue); if (root.isEmpty()) { // no root, create value as root root = newNode; } else { BinaryTree insertLocation = locate(root, newValue); if (insertLocation.value().compareTo(newValue) < 0) { insertLocation.setRight(newNode); } else if (!insertLocation.left().isEmpty()) { // handle interior duplicate node predecessor(insertLocation).setRight(newNode); } else { insertLocation.setLeft(newNode); } } } // remove top node (root) of tree, reconnect the tree, // return the new root of the tree private BinaryTree removeTop(BinaryTree top) { BinaryTree left = top.left(); BinaryTree right = top.right(); // disconnect the top from its children top.setLeft(new BinaryTree()); top.setRight(new BinaryTree()); // case 1: no left tree - remaining tree is just right if (left.isEmpty()) { return right; } // case 2: no right tree - remaining tree is just left if (right.isEmpty()) { return left; } BinaryTree pred = left.right(); // case 3: left node has no right subtree // "slide up" the left side of the tree if (pred.isEmpty()) { left.setRight(right); return left; } // case 4: general case - find the largest // value in the left subtree to be the new root BinaryTree parent = left; while (!pred.right().isEmpty()) { parent = pred; pred = pred.right(); } // newly chosen root (far-right) has no right subtree // but might have left; // left subtree takes the place of this node parent.setRight(pred.left()); // now pred becomes the new root pred.setLeft(left); pred.setRight(right); return pred; } public T remove(T item) { BinaryTree node = locate(root, item); if (!node.value().equals(item)) { // item not in BST, nothing to do return null; } if (node == root) { // deleting the root of the entire BST root = removeTop(root); } else if (node.parent().left() == node) { // node is a left child node.parent().setLeft(removeTop(node)); } else { // node is a right child node.parent().setRight(removeTop(node)); } return item; } }