Professional Documents
Culture Documents
First we develop a class AVLNode for the nodes in an AVL tree. The code is given below
and in the file avlnode.h.
template <class E, class K>
class AVLNode
{
friend AVLtree<E,K>;
public:
AVLNode() {LeftChild = RightChild = 0;}
AVLNode(const E& e)
{data = e; bf = 0; LeftChild = RightChild = 0;}
private:
E data;
int bf; // balance factor
AVLNode<E,K> *LeftChild, // left subtree
*RightChild; // right subtree
};
The interface for the class AVLtree is given below and in the file avl.h.
template<class E, class K>
class AVLtree
{ public:
AVLtree() {root = 0;}
~AVLtree() {Erase(root);}
bool Search(const K& k, E& e) const;
AVLtree<E,K>& Insert(const E& e);
AVLtree<E,K>& Delete(const K& k, E& e);
void Ascend()
{ InOutput(root);
cout << endl;
}
protected:
AVLNode<E,K> *root; // root node
void Erase(AVLNode<E,K> *t);
void InOutput(AVLNode<E,K> *t);
void FixBF(AVLNode<E,K> *,AVLNode<E,K>*, const E&);
1
void RRrotate(AVLNode<E,K> *,AVLNode<E,K>*, AVLNode<E,K> *);
void LLrotate(AVLNode<E,K> *,AVLNode<E,K>*, AVLNode<E,K> *);
void RLrotate(AVLNode<E,K> *,AVLNode<E,K>*, AVLNode<E,K> *);
void LRrotate(AVLNode<E,K> *,AVLNode<E,K>*, AVLNode<E,K> *);
};
Erase
template<class E, class K>
void AVLtree<E,K>::Erase(AVLNode<E,K> *t)
{// Delete all nodes in AVL tree with root t.
// Use a postorder traversal.
if (t)
{ Erase(t->LeftChild);
Erase(t->RightChild);
delete t;
}
}
Search
template<class E, class K>
AVLNode<E,K> *p = root;
if (k < p->data)
p = p->LeftChild;
2
else if (k > p->data)
p = p->RightChild;
else
{// found element
e = p->data;
return true;
}
return false;
q->bf = -1;
q = q->RightChild;
}
}
if (t)
{ InOutput(t->LeftChild);
InOutput(t->RightChild);
Rotations
template<class E, class K>
void AVLtree<E,K>::LLrotate(AVLNode<E,K> *PA,
AVLNode<E,K> *A, AVLNode<E,K> *B)
// restructure subtree at A
A->LeftChild = B->RightChild;
B->RightChild = A;
4
// set balance factors
A->bf = B->bf = 0;
}
// restructure subtree at A
A->RightChild = B->LeftChild;
B->LeftChild = A;
if (PA) // A is not the root
if (A == PA->LeftChild)
PA->LeftChild = B;
else
PA->RightChild = B;
else
root = B;
// set balance factors
A->bf = B->bf = 0;
}
template<class E, class K>
AVLNode<E,K> *C = B->RightChild;
5
// restructure subtree at A
A->LeftChild = C->RightChild;
B->RightChild = C->LeftChild;
C->LeftChild = B;
C->RightChild = A;
int b = C->bf;
if (b == 1)
{ B->bf = 0; A->bf = -1;
}
else if (b)
{ B->bf = 1; A->bf = 0;
}
else // b = 0
B->bf = A->bf = 0;
C->bf = 0;
6
void AVLtree<E,K>::RLrotate(AVLNode<E,K> *PA,
AVLNode<E,K> *C = B->LeftChild;
// restructure subtree at A
A->RightChild = C->LeftChild;
B->LeftChild = C->RightChild;
C->LeftChild = A;
C->RightChild = B;
int b = C->bf;
if (b == 1)
{ B->bf = -1; A->bf = 0;
}
else if (b)
{ B->bf = 0; A->bf = 1;
}
7
else // b = 0
B->bf = A->bf = 0;
C->bf = 0;
Insertion
template<class E, class K>
*pp = 0, // parent of p
*A = 0, // node with bf != 0
*PA; // parent of A
while (p)
{ // examine p->data
if (p->bf)
{ // new candidate for A node
A = p;
PA = pp;
}
pp = p;
8
// move p to a child
if (e < p->data)
p = p->LeftChild;
else if (e > p->data)
p = p->RightChild;
else throw
BadInput(); // duplicate
if (root)
{ // tree not empty
if (e < pp->data)
pp->LeftChild = r;
else
pp->RightChild = r;
}
else
{ // insertion into empty tree
root = r;
return *this;
}
9
A->bf = 0;
// fix bf on path from A to r
FixBF(A->LeftChild,r,e);
}
else
{ // insertion in right subtree
// bf of A is -2, rebalance
AVLNode<E,K> *B = A->RightChild;
if (e > B->data)
{ // RR case
FixBF(B->RightChild,r,e);
RRrotate(PA,A,B);
}
else
{ // RL case
FixBF(B->LeftChild,r,e);
RLrotate(PA,A,B);
}
}
}
else // bf = +1 before insertion
{ if (e > A->data)
{ // insertion in right subtree
// height of right subtree has increased by 1
// new bf of A is 0, no rebalancing
A->bf = 0;
FixBF(A->RightChild,r,e);
}
else
{ // insertion in left subtree
// bf of A is +2, rebalance
10
AVLNode<E,K> *B = A->LeftChild;
if (e < B->data)
{ // LL case
FixBF(B->LeftChild,r,e);
LLrotate(PA,A,B);
}
else
{ // LR case
FixBF(B->RightChild,r,e);
LRrotate(PA,A,B);
}
}
}
}
else // A is NULL, no rebalancing
FixBF(root,r,e);
return *this;
}
Deletion
template<class E, class K>
Stack<AVLNode<E,K>*> S(100);
11
// set p to point to node with key k
S.Add(p);
if (k < p->data)
p = p->LeftChild;
else
p = p->RightChild;
// restructure tree
// handle case when p has two children
S.Add(p);
AVLNode<E,K> *s = p->LeftChild;
while (s->RightChild)
{ // move to larger element
S.Add(s);
s = s->RightChild;
}
12
// move largest from s to p
p->data = s->data;
p = s;
}
AVLNode<E,K> *c;
if (p->LeftChild)
c = p->LeftChild;
else
c = p->RightChild;
// delete p
if (p == root)
root = c;
else
{ // is p a left or right child?
if (p == S.Top()->LeftChild)
S.Top()->LeftChild = c;
else
S.Top()->RightChild = c;
}
delete p;
// rebalance tree & correct BF, use stack to retrace path to root
// set q to parent of deleted node
AVLNode<E,K> *q;
try
{ S.Delete(q);
13
}
catch (OutOfBounds)
{ return *this; // root was deleted
}
while (q)
{
if (f <= q->data)
{ // deleted from left subtree of q
// height of left subtree reduced by 1
q->bf--;
if (q->bf == -1) // height of q is unchanged
return *this;
if (q->bf == -2)
{ // q is unbalanced
// classify imbalance and rotate
AVLNode<E,K> *B = q->RightChild,*PA;
// q is A node, PA is parent of A
try
{ S.Delete(PA);
}
catch (OutOfBounds)
{ PA = 0; // A is root
}
switch (B->bf)
{
case 0: // L0 imbalance
RRrotate(PA,q,B);
B->bf = 1;
q->bf = -1; // q is A node
return *this;
case 1: // L1 imbalance
RLrotate(PA,q,B);
break; // must continue on path to root
14
RRrotate(PA,q,B);
}
q = PA;
}
else
{ // q->bf is 0
try
{ S.Delete(q);
}
catch (OutOfBounds)
{ return *this;
}
}
}
else
{ // f > q->data
// deleted from right subtree of q
// height of right subtree reduced by 1
q->bf++;
if (q->bf == 1) // height of q is unchanged
return *this;
if (q->bf == 2)
{ // q is unbalanced,classify imbalance and rotate
AVLNode<E,K> *B = q->LeftChild,*PA;
// q is A node,PA is parent of A
try
{ S.Delete(PA);
}
catch (OutOfBounds)
{ PA = 0;
} // A is root
switch (B->bf)
{
case 0: // R0 imbalance
15
LLrotate(PA,q,B);
B->bf = -1;
q->bf = 1; // q is A node
return *this;
case 1: // R1 imbalance
LLrotate(PA,q,B);
break; // must continue on path to root
case -1: // R-1 imbalance
LRrotate(PA,q,B);
}
q = PA;
}
else
{ // q->bf is 0
try
{ S.Delete(q);
}
catch (OutOfBounds)
{ return *this;
}
}
}
}
return *this;
}
16