/** * AVLTree class - implements an AVL Tree by extending a binary * search tree. * * @author Michael Goodrich, Roberto Tamassia, Eric Zamore * * ++++++ Massacred by Cheung */ public class AVLTree { AVLNode root; int size; public static class Entry { String key; Integer value; } /** Nested class for the nodes of an AVL tree. */ public static class AVLNode { public Entry element; AVLNode left, right, parent; public int height; // height of this node AVLNode(Entry e) { element = e; left = right = parent = null; height = 0; } public void setHeight(int h) { height = h; } public int getHeight() { return height; } } public AVLTree() { root = null; size = 0; } /** Returns the height of a node (call back to an AVLNode). */ public int height(AVLNode p) { return p.getHeight(); } /** Sets the height of an internal node (call back to an AVLNode). */ public void recalcHeight(AVLNode p) { p.setHeight(1 + Math.max( height(p.left), height(p.right) ) ); } /** Returns whether a node has balance factor between -1 and 1. */ public boolean isBalanced(AVLNode p) { int bf; bf = height(p.left) - height(p.right); return ((-1 <= bf) && (bf <= 1)); } /** * Return a child of p with height no smaller than that of the * other child. */ public AVLNode tallerChild(AVLNode p) { if ( height(p.left) > height(p.right) ) return p.left; else if ( height(p.left) < height(p.right) ) return p.right; /* Equal height children - break tie using parent's type */ /* ------------------------------------ p = root: return it's left child ------------------------------------ */ if ( p == root )) return p.left; ------------------------------------ */ if ( p == left(parent(p)) ) { /* p is the left child of its parant */ return left(p); } else { /* p is the right child of its parant */ return right(p); } } /** Returns whether a node is internal. */ public boolean isInternal(AVLNode v) { if ( v.left != null || v.right != null ) return ( true ); else return ( false ); } /** * Rebalance method is called by insert and remove. * * Traverses the path from zPos to the root. * For each node encountered, we recompute its height * and perform a +++trinode restructuring+++ if it's unbalanced. */ public void rebalance(AVLNode zPos) { if ( isInternal(zPos) ) setHeight(zPos); /* ---------------------------------- Walk towards the root ---------------------------------- */ while ( zPos != root ) { zPos = zPos = zPos.parent; setHeight(zPos); if ( !isBalanced(zPos) ) { AVLNode xPos; /* ----------- perform a trinode restructuring at zPos's tallest grandchild ----------- */ xPos = tallerChild( tallerChild(zPos) ); zPos = restructure(xPos); // tri-node restructure (from parent class) /* ---------------------------- Recompute the heights.... ---------------------------- */ setHeight( zPos.left ); setHeight( zPos.right ); setHeight( zPos ); } } } /** Inserts an entry into the UNBALANCED tree and returns the newly created entry. */ public Entry insert(String k, Integer x) { AVLTree 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)); } /** * Inserts an item into the dictionary and returns the newly created * entry. */ public Entry insert(String k, Integer v) { Entry e; AVLNode n; e = new Entry(k, v); n = new AVLNode(e); Entry toReturn = super.insert(k, v); // calls our createNode method rebalance(actionPos); // rebalance up from the insertion position return toReturn; } /** Removes and returns an entry from the dictionary. */ public Entry remove(Entry ent) throws InvalidEntryException { Entry toReturn = super.remove(ent); if (toReturn != null) // we actually removed something rebalance(actionPos); // rebalance up the tree return toReturn; } }