package dictionary; import exceptions.InvalidEntryException; import position.NodePositionList; import position.Position; import position.PositionList; import priorityqueue.Entry; import tree.binarytree.BTPosition; import tree.binarytree.LinkedBinaryTree; import utility.DefaultComparator; import java.security.InvalidKeyException; import java.util.Comparator; public class BinarySearchTree extends LinkedBinaryTree> implements Dictionary { protected Comparator C; // comparator protected Position> actionPos; // insert node or removed node's parent protected int numEntries = 0; // number of entries public BinarySearchTree() { C = new DefaultComparator(); addRoot(null); } public BinarySearchTree(Comparator c) { C = c; addRoot(null); } /** Nested class for location-aware binary search tree entries */ protected static class BSTEntry implements Entry { protected K key; protected V value; protected Position> pos; BSTEntry(K k, V v, Position> p) { key = k; value = v; pos = p; } public K getKey() { return key; } public V getValue() { return value; } public Position> position() { return pos; } } /** Extracts the key of the entry at a given node of the tree. */ protected K key(Position> position) { return position.element().getKey(); } /** Extracts the value of the entry at a given node of the tree. */ protected V value(Position> position) { return position.element().getValue(); } /** Extracts the entry at a given node of the tree. */ protected Entry entry(Position> position) { return position.element(); } /** Replaces an entry with a new entry (and reset the entry's location) */ protected void replaceEntry(Position > pos, Entry ent) { ((BSTEntry) ent).pos = pos; replace(pos, ent); } protected void checkKey(K key) throws InvalidKeyException { if(key == null) throw new InvalidKeyException("null key"); } protected void checkEntry(Entry ent) throws InvalidEntryException { if(ent == null || !(ent instanceof BSTEntry)) throw new InvalidEntryException("invalid entry"); } protected Entry insertAtExternal(Position> v, Entry e) { expandExternal(v,null,null); replace(v, e); numEntries++; return e; } /** Auxiliary method for removing an external node and its parent */ protected void removeExternal(Position> v) { removeAboveExternal(v); numEntries--; } /** Auxiliary method used by find, insert, and remove. */ protected Position> treeSearch(K key, Position> pos) { if (isExternal(pos)) return pos; // key not found; return external node else { K curKey = key(pos); int comp = C.compare(key, curKey); if (comp < 0) return treeSearch(key, left(pos)); // search left subtree else if (comp > 0) return treeSearch(key, right(pos)); // search right subtree return pos; // return internal node where key is found } } // Adds to L all entries in the subtree rooted at v having keys equal to k protected void addAll(PositionList> L, Position> v, K k) { if (isExternal(v)) return; Position> pos = treeSearch(k, v); if (!isExternal(pos)) { // we found an entry with key equal to k addAll(L, left(pos), k); L.addLast(pos.element()); // add entries in inorder addAll(L, right(pos), k); } // this recursive algorithm is simple, but it's not the fastest } /** Returns the number of entries in the tree. */ public int size() { return numEntries; } /** Returns whether the tree is empty. */ public boolean isEmpty() { return size() == 0; } /** Returns an entry containing the given key. Returns null if no such entry exists. */ public Entry find(K key) throws InvalidKeyException { checkKey(key); // may throw an InvalidKeyException Position> curPos = treeSearch(key, root()); actionPos = curPos; // node where the search ended if (isInternal(curPos)) return entry(curPos); return null; } /** Returns an iterable collection of all the entries containing the given key. */ public Iterable> findAll(K key) throws InvalidKeyException { checkKey(key); // may throw an InvalidKeyException PositionList> L = new NodePositionList>(); addAll(L, root(), key); return L; } /** Inserts an entry into the tree and returns the newly created entry. */ public Entry insert(K k, V x) throws InvalidKeyException { checkKey(k); // may throw an InvalidKeyException Position> insPos = treeSearch(k, root()); while (!isExternal(insPos)) // iterative search for insertion position insPos = treeSearch(k, left(insPos)); actionPos = insPos; // node where the new entry is being inserted return insertAtExternal(insPos, new BSTEntry(k, x, insPos)); } /** Removes and returns a given entry. */ public Entry remove(Entry ent) throws InvalidEntryException { checkEntry(ent); // may throw an InvalidEntryException Position> remPos = ((BSTEntry) ent).position(); Entry toReturn = entry(remPos); // entry to be returned if (isExternal(left(remPos))) remPos = left(remPos); // left easy case else if (isExternal(right(remPos))) remPos = right(remPos); // right easy case else { // entry is at a node with internal children Position> swapPos = remPos; // find node for moving entry remPos = right(swapPos); do remPos = left(remPos); while (isInternal(remPos)); replaceEntry(swapPos, (Entry) parent(remPos).element()); } actionPos = sibling(remPos); // sibling of the leaf to be removed removeExternal(remPos); return toReturn; } /** Returns an iterator containing all entries in the tree. */ public Iterable> entries() { PositionList> entries = new NodePositionList>(); Iterable>> positer = positions(); for (Position> cur: positer) if (isInternal(cur)) entries.addLast(cur.element()); return entries; } }