package containers; import java.util.Enumeration; import binaryTree.*; import binaryTreeVisitor.*; import ordered.IOrdered; /** * An ordered container implemented using a binary search tree. The * binary search tree is implemented as visitors on the BiTree * structure. * * Version 1. * * @author Alan L. Cox * @since 04/09/01 */ public class BSTContainer implements IOrderedContainer { private BiTree _tree = new BiTree(); /** * Returns the BiTree that corresponds to the provided "key". If * the "key" matches an existing key-value pair within the tree, * the non-empty BiTree containing that key-value pair is returned. * Otherwise, an empty BiTree corresponding to "key"'s place in * the BST is returned. */ private BiTree findBiTreeFor(IOrdered key) { return (BiTree)_tree.execute(new IAlgo() { public Object emptyCase(BiTree host, Object input) { return host; } public Object nonEmptyCase(BiTree host, Object input) { OrderedKeyValuePair hostPair = (OrderedKeyValuePair)host.getRootData(); switch (((IOrdered)input).compare(hostPair.getKey())) { case IOrdered.LESS: return host.getLeftSubTree().execute(this, input); case IOrdered.EQUAL: return host; case IOrdered.GREATER: return host.getRightSubTree().execute(this, input); } throw new IllegalArgumentException( "unexpected value from compare()"); } }, key); } /** * If there is an object associated with key * then this object is returned else null is returned. */ public Object find(IOrdered key) { BiTree where = findBiTreeFor(key); return where.execute(new IAlgo() { public Object emptyCase(BiTree host, Object input) { return null; } public Object nonEmptyCase(BiTree host, Object input) { return ((OrderedKeyValuePair)host.getRootData()).getValue(); } }, null); } /** * Afterwards, find(key) returns null, and if there is * an object associated with key then this object is * returned else null is returned. */ public Object remove(IOrdered key) { BiTree where = findBiTreeFor(key); return where.execute(new IAlgo() { public Object emptyCase(BiTree host, Object input) { return null; } public Object nonEmptyCase(BiTree host, Object input) { Object value = ((OrderedKeyValuePair)host.getRootData()).getValue(); host.getLeftSubTree().execute(new IAlgo() { /** * If the left subtree is empty, remove its parent, * the outermost "host" (or "where"). */ public Object emptyCase(BiTree host, Object input) { ((BiTree)input).removeRoot(); return null; } /** * If the left subtree is non-empty, delegate * the operation to the right subtree. */ public Object nonEmptyCase(BiTree host, Object input) { ((BiTree)input).getRightSubTree().execute(new IAlgo() { /** * If the right subtree is empty, remove its * parent, the outermost "host" (or "where"). */ public Object emptyCase(BiTree host, Object input) { ((BiTree)input).removeRoot(); return null; } /** * If the left and right subtrees are non-empty, * replace the data in the outermost "host" with * the data from a BiTree that is removeable, i.e., * has one or fewer non-empty subtrees, and * maintains the BST property. The BiTree with * the smallest key in the right subtree satisfies * these requirements. */ public Object nonEmptyCase(BiTree host, Object input) { BiTree minTree = (BiTree) host.execute(LeftmostTreeFinder.Singleton, null); ((BiTree)input).setRootData( minTree.getRootData()); minTree.removeRoot(); return null; } }, input); return null; } }, host); return value; } }, null); } /** * (key, value) is stored in this container with no * duplication and such that find(key) returns value. */ public void insert(IOrdered key, Object value) { BiTree where = findBiTreeFor(key); where.execute(new IAlgo() { public Object emptyCase(BiTree host, Object input) { host.insertRoot(input); return null; } public Object nonEmptyCase(BiTree host, Object input) { host.setRootData(input); return null; } }, new OrderedKeyValuePair(key, value)); } /** * Returns an Enumeration of the container. The objects returned * by nextElement() are OrderedKeyValuePair's. * * @return an Enumeration of the container. */ public Enumeration enumeration() { return new InorderEnumeration(_tree); } }