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:

In this illustration, letters in circles denote single nodes and letters in boxes denote subtrees, which can possibly be null.

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

This case can be achieved by, for instance, inserting E when F was null. Making a right rotation in this case will not re-balance the tree at all:

The operation has simply unbalanced the tree in the other direction. When we encounter such situations, we instead do the following:

Choosing between a ROTATE-RIGHT and ROTATE-RIGHT-TWO-LEVELS is done by looking at the children of B. If B is left-heavy, then a ROTATE-RIGHT will not cause a new unbalance because the right child of B is not higher than the left child (see FIGURE 1). If B is right-heavy, then a ROTATE-RIGHT-TWO-LEVELS is necessary. The REBALANCE operation simply calculates the height of a node after an insertion or deletion, and then does the rotations, if any.

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 ]