AVL trees and rotations
A binary search tree that repairs itself: the balance factor and the AVL condition, the four cases LL, RR, LR and RL and their single and double rotations, insertion (at most one repair) and deletion (repairs up to the root), the fewest nodes of an AVL tree of a given height (a Fibonacci recurrence) and the resulting bound of about 1.44 log n on the height, and the cost of building and using AVL trees.
Why it exists
A binary search tree is fast only if it is shallow. Insert the keys 1, 2, 3, ... in order and it becomes a chain: height and every operation takes . An AVL tree (Adelson-Velsky and Landis) never lets that happen. It is a binary search tree that checks itself after every insertion and deletion and repairs any imbalance with a few pointer changes called rotations. The result is a height of in the worst case, so search, insert and delete are all in the worst case. It is the first self-balancing tree and the standard answer to "how can a search tree guarantee logarithmic time?".
Prerequisites
You need the binary search tree: the ordering rule, insertion and deletion (including the case of a node with two children and its in-order successor), and the fact that the shape depends on the insertion order. The size bound uses a recurrence solved like those in recurrences.
Precise definitions
Height. The height of a node is the number of edges on the longest downward path to a leaf. The height of an empty tree is , of a single node . (Some books say 1 for a single node and 0 for the empty tree; all heights then shift by one. A GATE question states its convention: read it.)
Balance factor of a node: .
AVL tree. A binary search tree in which every node has : the heights of its two subtrees differ by at most 1. (This is a condition on every node, not only on the root.)
Rotation. A local change of three pointers that keeps the in-order sequence of the keys unchanged and changes the heights:
- Right rotation at (with left child ): becomes the root of the subtree, becomes its right child, and the old right subtree of becomes the left subtree of .
- Left rotation at (with right child ): the mirror image.
The four cases. After an insertion (or deletion) let be the lowest node with .
| Case | Where the extra height is | Repair |
|---|---|---|
| LL | and | one right rotation at |
| RR | and | one left rotation at |
| LR | and | left rotation at the left child, then right rotation at |
| RL | and | right rotation at the right child, then left rotation at |
After an insertion the child's balance factor is never 0 in this situation; after a deletion it can be 0, and then a single rotation is correct (the cases LL and RR with the child at 0).
How it works
Insertion
Insert like in an ordinary search tree, then walk back up to the root, recompute heights and balance factors, and repair the first node that is out of balance.
AVL insertion: 10, 20, 30, 40, 50, 25: start
Computed by a script, not typed| key | Left | Right | Height | Balance |
|---|---|---|---|---|
| 10 | ||||
| 20 | ||||
| 25 | ||||
| 30 | ||||
| 40 | ||||
| 50 |
Step 0
Keys are inserted one after another. A row is a node: its left and right child (- = none), its height (a single node has height 0) and its balance factor (height of the left subtree minus the height of the right subtree). The table only fills as the nodes appear.
Each row is a node (the table fills as the keys arrive). Inserting 30 makes 10 right-heavy by two: the case RR, a single left rotation, and 20 becomes the root. Inserting 50 does the same at 30. Inserting 25 puts a node in the left subtree of the right child of 20: the case RL, which one rotation cannot fix, so there is a double rotation (a right rotation at 40, which lifts 30, then a left rotation at 20). The result has the root 30, with 20 (children 10 and 25) on the left and 40 (right child 50) on the right. Watch the Left and Right columns change at every rotation.
Insertion needs at most one repair. After the repair the subtree has the height it had before the insertion, so no ancestor sees a change. The check over all insertion orders of up to 8 keys found one rebalancing step at most (a double rotation is one step with two rotations).
The four cases
The four rebalancing cases: start
Computed by a script, not typed| case | Insertion order | Unbalanced node | Heavy side | Repair | Shape before | Shape after |
|---|---|---|---|---|---|---|
| LL | ||||||
| RR | ||||||
| LR | ||||||
| RL |
Step 0
The smallest tree for each case. The name says where the new node went relative to the unbalanced node z: the first letter is the side of the heavy child, the second the side of the grandchild.
In each case the middle key of the three becomes the root of the subtree, and the other two become its children; the pictures differ only in how the smaller subtrees are reattached. A double rotation is needed when the new node lies in the inner subtree (LR, RL) and a single one when it lies in the outer subtree (LL, RR).
Deletion
Delete like in an ordinary search tree (a node with two children is replaced by its in-order successor, which is then removed), then walk up from the place of the removal and repair every node that is out of balance. Unlike the insertion, the repair can shrink the subtree, so the parent may become unbalanced in turn:
AVL deletion: remove 11 from the smallest AVL tree of height 4: start
Computed by a script, not typed| key | Left | Right | Height | Balance |
|---|---|---|---|---|
| 1 | ||||
| 2 | ||||
| 3 | ||||
| 4 | ||||
| 5 | ||||
| 6 | ||||
| 7 | ||||
| 8 | ||||
| 9 | ||||
| 10 | ||||
| 11 | ||||
| 12 |
Step 0
Deleting a node can shorten a subtree, which unbalances an ancestor; repairing that ancestor can shorten its subtree again, and so on up to the root. The table shows the node table after each stage.
This is the smallest AVL tree of height 4 (12 nodes). Removing key 11 leaves 12 left-heavy by two; the repair shortens that subtree; now 8 is out of balance by two, and a second rotation is needed. In the worst case a deletion repairs at every level up to the root, so it may need rotations:
How many rotations does one operation need?: start
Computed by a script, not typed| operation | Nodes in the tree | Rebalancing steps | Rotations |
|---|---|---|---|
| any insertion (all orders of up to 7 keys) | |||
| worst deletion, smallest tree of height 2 | |||
| worst deletion, smallest tree of height 3 | |||
| worst deletion, smallest tree of height 4 | |||
| worst deletion, smallest tree of height 5 | |||
| worst deletion, smallest tree of height 6 | |||
| worst deletion, smallest tree of height 7 | |||
| worst deletion, smallest tree of height 8 |
Step 0
An insertion needs at most one rebalancing step (one single or one double rotation): after it the subtree is as high as before the insertion, so nothing above changes. A deletion can shorten the subtree, so rebalancing can repeat on the way up to the root.
(The table is a measurement of the smallest trees, not a proof of the worst case, but it shows the pattern: about half the height.)
How tall can an AVL tree be?
Let be the fewest nodes of an AVL tree of height . The sparsest such tree has a root, a subtree of height and a subtree of height (any shorter and the condition fails; any smaller subtree would shorten the whole tree):
This gives 1, 2, 4, 7, 12, 20, 33, 54, ... for , which is the Fibonacci sequence minus one: (with ). The most nodes of height is (a perfect tree).
Size and height of AVL trees: start
Computed by a script, not typed| height h | Fewest nodes N(h) | Most nodes | n for which h is the largest possible height | Smallest possible height for those n |
|---|---|---|---|---|
| height 0 | ||||
| height 1 | ||||
| height 2 | ||||
| height 3 | ||||
| height 4 | ||||
| height 5 | ||||
| height 6 | ||||
| height 7 | ||||
| height 8 | ||||
| height 9 | ||||
| height 10 |
Step 0
N(h) = N(h-1) + N(h-2) + 1 with N(0) = 1 and N(-1) = 0 is the fewest nodes of an AVL tree of height h: the root plus one subtree of height h-1 and one of height h-2. These are the Fibonacci numbers minus one.
Read the table from the right: an AVL tree with nodes has height at most the largest with . The exercise "what is the largest height of an AVL tree with 7 nodes?" is answered by the row for : 3. Because grows like with (the golden ratio), for every AVL tree, and for every binary tree. So the height is , between and about .
Sorted input
Sorted input: plain search tree against AVL: start
Computed by a script, not typed| keys | Height, plain tree | Height, AVL tree | Smallest possible height | Rebalancing steps | Rotations |
|---|---|---|---|---|---|
| n = 7 | |||||
| n = 15 | |||||
| n = 31 | |||||
| n = 63 | |||||
| n = 127 | |||||
| n = 255 | |||||
| n = 1023 |
Step 0
The worst input for a plain binary search tree: the keys arrive already sorted. The AVL tree repairs itself and stays shallow.
The plain tree becomes a chain, the AVL tree has the smallest possible height for every size shown. Inserting in order for costs rotations, all single, and ends in a perfect tree. The program below does the insertions with the exact rotation rules of this page.
#include <stdio.h>
#include <stdlib.h>
struct node {
int key, height;
struct node *left, *right;
};
static int rotations = 0;
static int height(const struct node *n) { return n ? n->height : -1; }
static int max(int a, int b) { return a > b ? a : b; }
static void update(struct node *n) { n->height = 1 + max(height(n->left), height(n->right)); }
static struct node *rotate_right(struct node *y) {
struct node *x = y->left;
y->left = x->right;
x->right = y;
update(y);
update(x);
rotations++;
return x;
}
static struct node *rotate_left(struct node *x) {
struct node *y = x->right;
x->right = y->left;
y->left = x;
update(x);
update(y);
rotations++;
return y;
}
static struct node *rebalance(struct node *n) {
update(n);
int balance = height(n->left) - height(n->right);
if (balance > 1) {
if (height(n->left->left) < height(n->left->right)) n->left = rotate_left(n->left); /* case LR */
return rotate_right(n);
}
if (balance < -1) {
if (height(n->right->right) < height(n->right->left)) n->right = rotate_right(n->right); /* case RL */
return rotate_left(n);
}
return n;
}
static struct node *insert(struct node *n, int key) {
if (n == NULL) {
n = calloc(1, sizeof *n);
if (n == NULL) exit(1);
n->key = key;
return n;
}
if (key < n->key) n->left = insert(n->left, key);
else if (key > n->key) n->right = insert(n->right, key);
else return n;
return rebalance(n);
}
static void show(const struct node *n) {
if (n == NULL) { printf("."); return; }
if (n->left == NULL && n->right == NULL) { printf("%d", n->key); return; }
printf("(");
show(n->left);
printf(" %d ", n->key);
show(n->right);
printf(")");
}
static void release(struct node *n) {
if (n == NULL) return;
release(n->left);
release(n->right);
free(n);
}
int main(void) {
int keys[] = {10, 20, 30, 40, 50, 25};
struct node *root = NULL;
for (int i = 0; i < 6; i++) {
root = insert(root, keys[i]);
printf("insert %d: ", keys[i]);
show(root);
printf(" rotations so far: %d\n", rotations);
}
release(root);
for (int n = 7; n <= 1023; n = 2 * n + 1) {
rotations = 0;
root = NULL;
for (int k = 1; k <= n; k++) root = insert(root, k);
printf("keys 1..%d in order: height %d, %d rotations\n", n, root->height, rotations);
release(root);
}
return 0;
}insert 10: 10 rotations so far: 0
insert 20: (. 10 20) rotations so far: 0
insert 30: (10 20 30) rotations so far: 1
insert 40: (10 20 (. 30 40)) rotations so far: 1
insert 50: (10 20 (30 40 50)) rotations so far: 2
insert 25: ((10 20 25) 30 (. 40 50)) rotations so far: 4
keys 1..7 in order: height 2, 4 rotations
keys 1..15 in order: height 3, 11 rotations
keys 1..31 in order: height 4, 26 rotations
keys 1..63 in order: height 5, 57 rotations
keys 1..127 in order: height 6, 120 rotations
keys 1..255 in order: height 7, 247 rotations
keys 1..511 in order: height 8, 502 rotations
keys 1..1023 in order: height 9, 1013 rotationsThe rotation counts of the table are the counts of this program, and the shapes are the ones of the node table. (A double rotation counts as two rotations here.)
Cost
Search, insertion and deletion each follow one path from the root and do a constant amount of work per node (a deletion may repair at every level), so each takes in the worst case. Building a tree by insertions takes . Inserting keys into a tree that already has nodes costs in total in the worst case (every new node is a leaf, and every leaf of an AVL tree with nodes lies at a depth of at least about half its height, so each insertion walks nodes). Sorting by inserting into an AVL tree and reading it in order takes , a worst-case guarantee that a plain search tree does not give. The extra cost is one height (or balance factor) stored in every node and the code for the rotations.
Worked examples
EX 1Which case, which repair?
EasyInsert 50, 40, 30 into an empty AVL tree. After 30, node 50 has balance and its left child 40 has balance : the case LL. One right rotation at 50 gives the root 40 with children 30 and 50. Insert 50, 30, 40 instead: after 40, node 50 has balance and its left child 30 has balance : the case LR. Rotate left at 30 (40 becomes the left child of 50 with 30 below it), then right at 50: root 40, children 30 and 50. Both orders end in the same tree, because the middle key must become the root.
EX 2Largest and smallest height
Medium(a) What is the largest possible height of an AVL tree with 20 nodes? , so height 5. With 19 nodes, : height 4. (b) What is the fewest nodes in an AVL tree of height 6? . (c) What is the smallest height of a binary tree with 20 nodes? A perfect tree of height has nodes, and , so height 4. An AVL tree with 20 nodes has height 4 or 5. (d) If a book counts a single node as height 1, add one to each answer.
EX 3Insert and rebalance by hand
MediumBuild an AVL tree from 20, 10, 30, 5, 15, 25, 35, 3, 1. The first seven keys make a perfect tree with root 20. Insert 3: it goes below 5, to the left; heights are fine (node 10 has balance ). Insert 1: it goes left of 3. Now node 5 has balance (left subtree 3-1 of height 1, right subtree empty, height ) and its left child 3 has balance : the case LL at 5. Right rotation: 3 becomes the root of that subtree with children 1 and 5. Node 10 is balanced again (): nothing higher up changes, as expected for an insertion. The tree, written (left key right), is .
EX 4Typical questions
GATE level(a) "How many rotations does it take to insert 1, 2, 3, ..., 15 in order?" The program's table: 11 single rotations (it is for ). (b) "The maximum height of an AVL tree with 7 nodes, with height of a single node 0?" , so 3. (c) "Insert elements into an AVL tree with elements: worst-case time?" ; with this is . (d) "Which statement is true: an insertion needs at most one (single or double) rotation, a deletion may need ." Both are true. (e) "Is every AVL tree a balanced binary tree in the sense that all leaves are at the same level?" No, only the heights of the two subtrees of every node differ by at most 1. (f) "Is a node's balance factor enough to find the rotation?" Yes, the balance factors of and of its heavy child decide between LL, RR, LR and RL.
Cheat box
Cheat box
- AVL: at every node. Balance factor . Height of one node , of nothing .
- Cases: LL and RR need one rotation; LR and RL need two (the inner subtree is heavy).
- Insertion: at most one repair (one single or one double rotation). Deletion: possibly one repair per level, rotations.
- Fewest nodes: : 1, 2, 4, 7, 12, 20, 33, 54, ... (). Most nodes: .
- Height of an AVL tree with nodes: at most the largest with , and about at worst. All operations worst case.
Traps and GATE patterns
Connections
Builds on
Unlocks
The AVL tree repairs the weakness of the binary search tree, the dependence of the height on the insertion order. The B-tree solves the same problem differently, by allowing many keys per node and splitting nodes, which suits disks. Unlike the binary heap, an AVL tree keeps all keys sorted, so it can answer range queries and find a successor in .
PYQs
2 previous year questions from your book. I re-solved each one myself (1 by running or simulating, 1 by reasoning only); the book's key is shown next to my answer. All PYQs
What is the worst case time complexity of inserting n2 elements into an AVL-tree with n elements initially?
- (a)Θ(n4)
- (b)Θ(n2)
- (c)Θ(n3)
- (d)Θ(n2 log n)
What is the maximum height of any AVL-tree with 7 nodes ? Assume that the height of a tree with a single node is 0.
- (a)2
- (b)3
- (c)4
- (d)5
Self-check
Question 1
An AVL tree has root 40 with a left subtree of height 2 and a right subtree of height 0. Is it an AVL tree? What is the balance factor of 40?
Show answerHide
The balance factor is , so it is not an AVL tree (the condition allows ).
Question 2
What is the smallest number of nodes in an AVL tree of height 5 (a single node has height 0)?
Show answerHide
.
Question 3
Insert 3, 1, 2 into an empty AVL tree. Which case, and what is the result?
Show answerHide
After 2, node 3 has balance and its left child 1 has balance : the case LR. Rotate left at 1 (2 becomes the left child of 3), then right at 3: root 2 with children 1 and 3.
Revision card
One-screen revision
- AVL: every node has . Repair at the lowest unbalanced node .
- LL, RR: one rotation; LR, RL: two rotations. Middle key becomes the subtree root.
- Insertion: at most one repair. Deletion: up to repairs; child balance 0 means a single rotation.
- Fewest nodes : 1, 2, 4, 7, 12, 20, 33. Height .
- All operations worst case; sorted input is no problem.
References
- ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms, 3rd ed., Problem 13-3 (AVL trees) and Chapter 12 (binary search trees)
- ·Weiss, Data Structures and Algorithm Analysis in C, 2nd ed., Section 4.4 AVL Trees
- ·Knuth, The Art of Computer Programming, Volume 3, Section 6.2.3 Balanced Trees
Verification
scripts/enum-checks/pds_avl_check.py: (1) a second implementation (immutable tuples, heights recomputed from the structure on demand, rotations written separately) builds the same tree as scripts/avl_lib.py for EVERY insertion order of up to 8 keys (46233 orders), and for every deletion of every key from each of the 35 different AVL trees that insertion orders of up to 7 keys produce (197 deletions); (2) every tree is a binary search tree, satisfies the AVL condition (checked with heights recomputed from the structure, not the stored ones) and has correct stored heights, after every insertion and every deletion; (3) an insertion needs at most one rebalancing step in all these cases, and the worst deletions of the smallest AVL trees of height 2 to 8 need floor(h/2) steps (measured, not a proof that this is the worst case over all trees); (4) the sizes of AVL trees are found by a dynamic program on the sets of possible sizes per height up to height 12 and by generating every AVL SHAPE up to height 4: the fewest nodes of height h is N(h) = N(h-1) + N(h-2) + 1, the most 2^(h+1) - 1, and every size between occurs; (5) the largest height of an AVL tree with n nodes (n up to 200) equals the maximum over all AVL trees of that size, and the largest height reached by insertion orders of up to 8 keys equals it; for n up to 10^6 it stays below 1.4405 log2(n + 2); (6) the C program printed on the page is compiled and run and its output equals the library's trees and rotation counts. tests/pds-avl-traces.test.ts recomputes the node tables of the insertion and the sizes in TypeScript. CONVENTIONS: the height of an empty tree is -1 and of a single node 0 (a book that counts a single node as height 1 gives every height one more, and every answer 'h' becomes 'h + 1'); the balance factor is height(left) - height(right); deleting a node with two children uses the in-order successor; after a deletion the child's balance factor 0 needs one single rotation; a double rotation counts as one rebalancing step and two rotations. Textbook chapter and section numbers are from memory and need verification. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand (long C programs were not re-read line by line: they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose). One imprecise phrase fixed (the double rotation after inserting 25 is a right rotation at 40 and a left rotation at 20). Status raised to self-checked; verified needs a textbook or human check.
last verified: never
My notes (saved in this browser)