Self-Balancing & Advanced Trees
AVL tree balance factors and rotations, Red-Black tree properties, and Trie prefix trees
Standard Binary Search Trees suffer from a catastrophic worst-case: when elements are inserted in sorted or near-sorted order, the tree degenerates into a linear chain with height O(n), destroying O(log n) performance. Self-balancing trees restore height balance after insertions and deletions through tree rotations.
1. AVL Trees (Strict Balance)
Invented by Adelson-Velsky and Landis (1962), an AVL Tree is a self-balancing binary search tree where the height difference (the Balance Factor) of the left and right subtrees of any node cannot exceed 1.
Balance Factor (BF) = height(left) - height(right)Valid balance factor values are strictly -1, 0, or +1.
If BF > 1 or BF < -1, the tree is rebalanced via one of four rotation operations:
The Four Rotation Mechanics
Applied when an insertion occurs in the left subtree of a left child:
z (BF = +2) y
/ / \
y ===> x z
/
xprivate TreeNode rightRotate(TreeNode z) {
TreeNode y = z.left;
TreeNode T3 = y.right;
// Perform rotation
y.right = z;
z.left = T3;
return y; // New root of subtree
}2. Red-Black Trees (Industrial Standard)
A Red-Black Tree relaxes AVL's strict height balance to minimize rotation overhead during frequent insertions and deletions. It guarantees that no root-to-leaf path is more than twice as long as any other path, keeping height bounded by 2 * log2(n + 1).
The 5 Red-Black Invariants
null leaf pointer (NIL) is considered Black.Red Constraint (No Consecutive Reds) If a node is Red, both of its children must be
Black. No path can contain two red nodes in a row.
Black-Height Invariant Every path from any given node down to its descendant null leaves
must contain the exact same number of black nodes.
Where Java Uses Red-Black Trees
Because Red-Black trees require at most 2 rotations for an insertion and at most 3 rotations for a deletion, Java utilizes them for its primary sorted collections:
java.util.TreeMap: Red-black tree key-value mapping.java.util.TreeSet: Red-black tree unique sorted set (backed byTreeMap).java.util.HashMap: Bins that accumulate 8 or more colliding entries in tables of capacity 64 or greater treeify into Red-BlackTreeNodebuckets, bounding worst-case collision lookup atO(log n).
AVL vs Red-Black Tree Comparison
| Feature | AVL Tree | Red-Black Tree |
|---|---|---|
| Strictness of Balance | Stricter (BF <= 1) | Looser (path lengths differ at most 2x) |
| Maximum Height | ~1.44 * log2(n) | <= 2 * log2(n + 1) |
| Lookup Speed | Faster (flatter tree structure) | Slightly slower |
| Insert / Delete Overhead | Slower (more rotations required) | Faster (at most 2–3 rotations per mutation) |
| Best Used For | Read-intensive workloads | Write-intensive & general-purpose systems |
3. Trie (Prefix Tree)
A Trie (pronounced "try") is an n-ary tree used for storing and searching strings where all descendants of a node share a common string prefix:
Java Trie Implementation
public class Trie {
private static class TrieNode {
TrieNode[] children = new TrieNode[26];
boolean isEndOfWord = false;
}
private final TrieNode root = new TrieNode();
// Inserts word into trie: O(L) time where L is word length
public void insert(String word) {
TrieNode curr = root;
for (char ch : word.toCharArray()) {
int idx = ch - 'a';
if (curr.children[idx] == null) {
curr.children[idx] = new TrieNode();
}
curr = curr.children[idx];
}
curr.isEndOfWord = true;
}
// Returns true if word is in trie: O(L) time
public boolean search(String word) {
TrieNode node = findNode(word);
return node != null && node.isEndOfWord;
}
// Returns true if there is any word starting with prefix: O(L) time
public boolean startsWith(String prefix) {
return findNode(prefix) != null;
}
private TrieNode findNode(String str) {
TrieNode curr = root;
for (char ch : str.toCharArray()) {
int idx = ch - 'a';
if (curr.children[idx] == null) return null;
curr = curr.children[idx];
}
return curr;
}
}Trie Complexity: - Insertion: O(L) where L is the string length. - Prefix Search:
O(L) independent of how many millions of words exist in the dictionary! - Primary
Applications: Search autocomplete, spell checkers, IP routing (longest prefix match), and Word
Search II.