The balance of the tree is kept by storing the height of each node and comparing left and right childrens' heights to determine whether a rotation is necessary or not.
A rotation is necessary when the height difference between the two childs of a node is greater than 1.
For instance, if the left child of a node is 6 links high and the right child is 4 links high, then we can
make a new subtree by rotating the subtree to right, resulting in two 5-high children. This operation is
illustrated below:

This operation by itself is not enough to maintain a balance in all cases, though. Consider the following
situation:



REBALANCE (A):
calculate_height (A);
P= parent of A.
U= height( A.left ) - height( A.right )
if (U<-1)
if left_heavy(A.right)
rotate_left_twolevels(A)
else
rotate_left(A)
else if (U>1)
if right_heavy(A.left)
rotate_right_twolevels(A)
else
rotate_right(A)
rebalance(P);
As you can see, REBALANCE works up to the top of the tree.
-[ c library "avl.c", header "avl.h" ]
-[public] typedef struct anode {
struct anode *left, *right, *parent;
int height;
int data;
} anode_t;
-[public] typedef struct {
anode_t *root;
} atree_t;
-[public] void atree_insert (atree_t * T, int data)
{
node_t *N;
anode_t *P;
N = calloc (1, sizeof (*N));
N->data = data;
N->height = 1;
if (!T->root)
{
T->root = N;
return;
}
P = T->root;
while (1)
{
if (N->data < P->data)
{
if (P->left)
P = P->left;
else
{
P->left = N;
N->parent = P;
break;
}
}
else if (N->data > P->data)
{
if (P->right)
P = P->right;
else
{
P->right = N;
N->parent = P;
break;
}
}
else
{
free (N);
return;
}
}
rebalance (T, N);
}
-[private] void calculate_height (anode_t * N)
{
int L, R;
L = theight (N->left);
R = theight (N->right);
if (L > R)
N->height = L + 1;
else
N->height = R + 1;
}
-[private] void rebalance (atree_t * T, anode_t * N)
{
int u;
anode_t *P;
calculate_height (N);
u = theight (N->left) - theight (N->right);
P = N->parent;
if (u < -1) {
if (left_heavy (N->right))
rotate_left_twolevels (T, N);
else
rotate_left (T, N);
} else if (u > 1) {
if (right_heavy (N->left))
rotate_right_twolevels (T, N);
else
rotate_right (T, N);
}
if (P)
rebalance (T, P);
}
-[private] void replace_child_in_parent
(atree_t * T, anode_t * old, anode_t * nw)
{
if (old->parent) {
if (old->parent->left == old)
old->parent->left = nw;
else
old->parent->right = nw;
} else {
T->root = nw;
}
}
-[private] void rotate_right
(atree_t * T, anode_t * A)
{
anode_t *B;
B = A->left;
A->left = B->right;
if (A->left)
A->left->parent = A;
B->parent = A->parent;
replace_child_in_parent (T, A, B);
B->right = A;
A->parent = B;
calculate_height (A);
calculate_height (B);
}
-[private] void rotate_right_twolevels
(atree_t * T, anode_t * A)
{
anode_t *B, *C;
B = A->left;
C = B->right;
/* we know that B and C are non-null since
A was left heavy and B was right heavy */
A->left = C->right;
if (A->left)
A->left->parent = A;
B->right = C->left;
if (B->right)
B->right->parent = B;
C->parent = A->parent;
replace_child_in_parent (T, A, C);
C->left = B;
C->right = A;
A->parent = C;
B->parent = C;
calculate_height (A);
calculate_height (B);
calculate_height (C);
}
-[private] int right_heavy (anode_t * A)
{
if (!A) return 0;
return (theight (A->right) - theight (A->left)) > 0;
}
-[private] void
rotate_left (atree_t * T, anode_t * A)
{
anode_t *B;
B = A->right;
A->right = B->left;
if (A->right)
A->right->parent = A;
B->parent = A->parent;
replace_child_in_parent (T, A, B);
B->left = A;
A->parent = B;
calculate_height (A);
calculate_height (B);
}
-[private] void rotate_left_twolevels
(atree_t * T, anode_t * A)
{
anode_t *B, *C;
B = A->right;
C = B->left;
/* we know that B and C are non-null since
A was right heavy and B was left heavy */
A->right = C->left;
if (A->right)
A->right->parent = A;
B->left = C->right;
if (B->left)
B->left->parent = B;
C->parent = A->parent;
replace_child_in_parent (T, A, C);
C->right = B;
C->left = A;
A->parent = C;
B->parent = C;
calculate_height (A);
calculate_height (B);
calculate_height (C);
}
-[private] int
left_heavy (anode_t * A)
{
if (!A) return 0;
return (theight (A->left) - theight (A->right)) > 0;
}
-[private] int theight (anode_t * A)
{
if (A) return A->height;
else return 0;
}
-[ headers, begin ]
!stdlib
-[ end ]