Overview
AVL and Red-Black trees are Self-Balancing Binary Search Trees (BSTs). In a standard BST, if elements are inserted in sorted order, the tree becomes a linked list (degenerate), leading to $O(n)$ search time. Self-balancing trees ensure the height remains $O(\log n)$ by rotating nodes during insertion and deletion.
Core Concepts
- AVL Trees:
- Strict Balancing: The height difference between the left and right subtrees (the Balance Factor) of any node can be at most 1.
- Rotations: Uses Single (LL, RR) and Double (LR, RL) rotations to fix imbalances.
- Performance: Faster lookups than Red-Black trees due to stricter balancing, but slower insertions/deletions due to more rotations.
- Red-Black Trees:
- Approximate Balancing: Uses a coloring scheme (Red or Black) and a set of rules to ensure the tree is “roughly” balanced.
- Rules:
- Every node is either red or black.
- The root is always black.
- Red nodes cannot have red children (no two consecutive reds).
- Every path from a node to its descendant NULL nodes must contain the same number of black nodes.
- Performance: Faster insertions and deletions than AVL trees. Used in many standard libraries (e.g., Java’s
TreeMap, C++’sstd::map).
Code Examples
// Conceptual AVL rotation
function rotateRight(y: Node): Node {
let x = y.left;
let T2 = x.right;
// Perform rotation
x.right = y;
y.left = T2;
// Update heights
y.height = Math.max(getHeight(y.left), getHeight(y.right)) + 1;
x.height = Math.max(getHeight(x.left), getHeight(x.right)) + 1;
return x; // New root
}
Use Cases
- Databases: Indexing large datasets where search, insertion, and deletion must all stay $O(\log n)$.
- Memory Maps: Implementing associative arrays/maps in standard libraries.
- Virtual Memory: Managing memory regions in OS kernels.
Gotchas
- Implementation Complexity: Implementing these trees from scratch is error-prone due to the many rotation and recoloring cases.
- Overhead: For small datasets, a simple BST or even an array might be faster due to lower constant overhead.
