|
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)
|