|
We will first discuss how to maintain height information in a BST before we discuss AVL trees
|
public class BSTEntry { public String key; // Key public Integer value; // Value public int height; // Height information public BSTEntry parent; public BSTEntry left; public BSTEntry right; } |
Leaf node: Height( leaf node ) = 1 |
Example:
|
|
Tree before insert operation | Tree after insert operation |
---|---|
Tree before insert operation | Tree after insert operation |
---|---|
Tree before delete operation | Tree after delete operation |
---|---|
Tree before delete operation | Tree after delete operation |
---|---|
|
|
Tree before insert operation | Tree after insert operation |
---|---|
Tree before delete operation | Tree after delete operation |
---|---|
|
|
we can write the following recompHeight() method:
/* ================================================================ recompHeight(x): recompute height starting at x (and up) ================================================================ */ public static void recompHeight( BSTEntry x ) { while ( x != null ) { x.height = maxHeight( x.left, x.right ) + 1; // Compute height for x x = x.parent; // Go to the parent node } } |
|
|
|
public void put(String k, Integer v) { BSTEntry p; // Help variable /* ---------------------------------------------------------- Just like linked list, insert in an EMPTY BST must be taken care off separately by an if-statement ---------------------------------------------------------- */ if ( root == null ) { // Insert into an empty BST root = new BSTEntry( k, v ); root.height = 1; return; } /* -------------------------------------------- Find the node with key == "key" in the BST -------------------------------------------- */ p = findEntry(k); if ( k.equals( p.key ) ) { p.value = v; // Update value return; } /* -------------------------------------------- Insert a new entry (k,v) under p !!! -------------------------------------------- */ BSTEntry q = new BSTEntry( k, v ); q.height = 1; q.parent = p; /* ************************************************* Upto here, it's just the OLD put() method ************************************************* */ /* --------------------------------------------------- Action location = q The parent of q = q So: recompute the height of all nodes starting at p --------------------------------------------------- */ recompHeight(p); } |
public void remove(String k) { BSTEntry p, q; // Help variables BSTEntry parent; // parent node BSTEntry succ; // successor node /* -------------------------------------------- Find the node with key == "key" in the BST -------------------------------------------- */ p = findEntry(k); if ( ! k.equals( p.key ) ) return; // Not found ==> nothing to delete.... /* ======================================================== Hibbard's Algorithm ======================================================== */ if ( p.left == null && p.right == null ) // Case 0: p has no children { parent = p.parent; /* -------------------------------- Delete p from p's parent -------------------------------- */ if ( parent.left == p ) parent.left = null; else parent.right = null; /* -------------------------------------------- parent = parent of the deleted node Recompute height starting at "parent"... -------------------------------------------- */ recompHeight( parent ); return; } if ( p.left == null ) // Case 1a: p has 1 (right) child { parent = p.parent; /* ---------------------------------------------- Link p's right child as p's parent child ---------------------------------------------- */ if ( parent.left == p ) parent.left = p.right; else parent.right = p.right; /* -------------------------------------------- parent = parent of the deleted node Recompute height starting at "parent"... -------------------------------------------- */ recompHeight( parent ); return; } if ( p.right== null ) // Case 1b: p has 1 (left) child { parent = p.parent; /* ---------------------------------------------- Link p's left child as p's parent child ---------------------------------------------- */ if ( parent.left == p ) parent.left = p.left; else parent.right = p.left; /* -------------------------------------------- parent = parent of the deleted node Recompute height starting at "parent"... -------------------------------------------- */ recompHeight( parent ); return; } /* ================================================================ Tough case: node has 2 children - find successor of p succ(p) is as as follows: 1 step right, all the way left Note: succ(p) has NOT left child ! ================================================================ */ succ = p.right; // p has 2 children.... while ( succ.left != null ) succ = succ.left; p.key = succ.key; // Replace p with successor p.value = succ.value; /* -------------------------------- Delete succ from succ's parent -------------------------------- */ parent = succ.parent; if ( parent.left == succ ) parent.left = succ.right; // parent skip over succ ... else parent.right = succ.right; // ... and point to succ's right child /* -------------------------------------------- parent = parent of the deleted node Recompute height starting at "parent"... -------------------------------------------- */ recompHeight( parent ); return; } |
How to run the program:
|
Output:
[lion,9999](h=1) ================================ [lion,9999](h=2) [dog,1000](h=1) ================================ [lion,9999](h=3)* [dog,1000](h=2) [cat,500](h=1) ================================ [tiger,8888](h=1) [lion,9999](h=3) [dog,1000](h=2) [cat,500](h=1) ================================ [tiger,8888](h=1) [lion,9999](h=3) [horse,2000](h=1) [dog,1000](h=2) [cat,500](h=1) ================================ [tiger,8888](h=1) [lion,9999](h=4)* [horse,2000](h=1) [dog,1000](h=3) [cat,500](h=2) [ape,1500](h=1) |