Balanced Trees

←Back to Tech Tree

inventorycoverage

Balanced Trees #

Data StructuresDifficulty: ★★★☆☆Depth: 5Unlocks: 0

AVL, Red-Black trees. O(log n) operations guaranteed.

Interactive Visualization #

⏮◀◀▶▶STEP0.25x1xZOOM

t=0s

Core Concepts #

Essential Relationships #

Prerequisites (2) #

Binary Search Trees5 atomsBig O Notation6 atoms

Advanced Learning Details

Graph Position #

58

Depth Cost

0

Fan-Out (ROI)

0

Bottleneck Score

5

Chain Length

Cognitive Load #

4

Atomic Elements

37

Total Elements

L2

Percentile Level

L2

Atomic Level

All Concepts (18) #

Teaching Strategy #

Quick unlock - significant prerequisite investment but simple final step. Verify prerequisites first.

A plain Binary Search Tree (BST) is fast only when it stays tree-shaped. Balanced trees are the engineering answer to the worst case: they enforce small local rules so the whole tree can’t silently collapse into a linked list.

TL;DR:

Balanced trees (AVL and Red-Black) maintain a BST plus a local balance invariant. When an insert/delete breaks the invariant, they fix it using a small set of local rotations (and sometimes recoloring). Those local rules imply the height is O(log n), so search/insert/delete are guaranteed O(log n).

What Is Balanced Trees? #

A Balanced Tree is a Binary Search Tree that actively prevents itself from becoming too tall.

Why this matters: In a regular BST, search/insert/delete follow one root-to-leaf path. If the tree height is h, these operations take O(h). In the best case h ≈ log₂ n, but in the worst case (inserting sorted keys) h = n − 1, so operations degrade to O(n).

Balanced trees enforce a local invariant at each node—some small constraint about the relationship between its children. The key idea is:

Two classic families:

  1. AVL trees
  1. Red-Black trees

Both guarantee O(log n) search/insert/delete, but they trade off how strict the balancing is and how much work they do to maintain it.

A helpful mental model: balancing is not about making the tree perfectly symmetric—it's about ensuring you never get a long skinny path.

What “guaranteed O(log n)” really means #

If n is the number of keys and the height is h, then:

Balanced trees ensure h ≤ c · log₂(n + 1) for some constant c.

So you keep predictable performance even under adversarial insertion orders.

Core Mechanic 1: Tree Rotations (Local Restructuring Without Breaking Order) #

Balanced trees rely on a single surgical tool: the rotation.

Why rotations exist: When a subtree becomes too tall on one side, we want to “tilt” it to redistribute height—but we must preserve the BST in-order property:

A rotation changes the shape while keeping the in-order sequence of keys exactly the same.

Left rotation #

Consider a node x with right child y. A left rotation makes y the parent and x the left child.

Before:

After rotating left at x:

Key ordering remains valid because:

Right rotation #

Symmetric: rotate right at y when y has left child x.

Before:

After rotating right at y:

In-order preservation (why it works) #

Think in terms of in-order traversal:

For the left rotation case, the in-order order of the local nodes/subtrees is:

After rotation, in-order becomes:

It’s identical.

Rotations and heights #

Rotations are used because they change subtree heights in a controlled way.

If we define height as:

A rotation modifies only a constant-sized region, so height updates are local:

Double rotations #

Sometimes a single rotation is not enough. Two common cases:

These “double rotations” still act locally but correct more complex imbalance patterns.

Summary table: rotations #

OperationTrigger patternLocal effectPreserves BST order?
Left rotationright-heavy at xpromotes x.rightYes
Right rotationleft-heavy at ypromotes y.leftYes
LR (double)left child is right-heavytwo-step rebalanceYes
RL (double)right child is left-heavytwo-step rebalanceYes

Rotations are the backbone of both AVL and Red-Black trees. The difference is the invariant that tells you when to rotate (and what extra metadata to update).

Core Mechanic 2: Local Balance Invariants (AVL vs Red-Black) #

A balanced tree is defined less by rotations and more by the rule that determines when rotations are required.

AVL invariant (balance factor) #

AVL trees track a height-based constraint at every node.

Define the balance factor:

bf(node) = height(left) − height(right)

AVL requires:

bf(node) ∈ {−1, 0, +1} for every node

Why this helps: If every node’s subtrees differ in height by at most 1, then long skewed chains can’t form.

AVL insertion repair (intuition) #

Insertion is normal BST insertion first. Then, as you walk back up toward the root, you update heights and check balance factors.

If a node becomes unbalanced, bf becomes ±2, and you fix it using one of four cases:

A useful feature: for AVL insertion, after you rebalance at the first unbalanced node on the path upward, the subtree height is restored in a way that often stops further fixes.

AVL deletion repair (intuition) #

Deletion can reduce heights, which may cause multiple ancestors to become unbalanced. AVL deletion may require rebalancing repeatedly up to the root.

Red-Black invariant (color + black-height) #

Red-Black trees store one extra bit per node: color ∈ {red, black}.

They satisfy (one common formulation):

  1. Every node is red or black.

  2. The root is black.

  3. All leaves (nulls) are black.

  4. If a node is red, then both its children are black. (No two consecutive reds.)

  5. For any node, every path from that node to any descendant leaf has the same number of black nodes. (Equal black-height.)

Why this helps:

Red-Black balancing is looser than AVL. It allows more shape variation, but still guarantees logarithmic height.

Height bound consequence (the big promise) #

Balanced trees work because local constraints imply global height bounds.

Red-Black height sketch #

Let bh be the black-height of the root (number of black nodes on any root→leaf path, excluding null leaf depending on convention).

From rule (4), between black nodes you can have at most one red node. So any root→leaf path has length at most:

h ≤ 2 · bh

Also, a subtree with black-height bh has at least 2ᵇʰ − 1 internal nodes (because each black level must branch enough to maintain that black-height; formally, the minimum-node RB tree of black-height bh is a perfect black-only tree).

So if n ≥ 2ᵇʰ − 1, then:

n + 1 ≥ 2ᵇʰ

log₂(n + 1) ≥ bh

Combine with h ≤ 2 · bh:

h ≤ 2 · log₂(n + 1)

Therefore search/insert/delete are O(log n).

AVL height sketch #

AVL trees are even tighter. Let N(h) be the minimum number of nodes in an AVL tree of height h.

To minimize nodes for height h, you want children heights to be as small as allowed while still making height h:

So:

N(h) = 1 + N(h − 1) + N(h − 2)

With base cases:

This is Fibonacci-like growth, implying N(h) grows exponentially in h, so h grows logarithmically in n.

A standard bound is:

h ≤ 1.44 · log₂(n + 2) − 1

The exact constant isn’t the key takeaway; the takeaway is: AVL forces h = O(log n) via a stricter local rule.

AVL vs Red-Black: practical comparison #

FeatureAVLRed-Black
Local invariantbf
Height boundtighter (shorter trees)looser (slightly taller)
Search performancetypically slightly bettertypically slightly worse
Insert/delete fix-upmay do more rotations/height updatesoften fewer rotations; recoloring common
Typical useread-heavy workloads, indexinggeneral-purpose maps/sets in many libs

Both are excellent. The right choice is often about engineering tradeoffs, not asymptotic complexity.

Application/Connection: Guaranteeing O(log n) Maps/Sets and Beyond #

Balanced trees show up whenever you need an ordered collection with predictable performance.

Ordered maps and sets #

Balanced trees implement:

But unlike hash tables, they also support order-aware operations efficiently:

Because height is O(log n):

Why not just use hashing? #

Hash tables are great for average-case O(1) lookups, but:

Balanced trees give a clean, deterministic guarantee.

Where AVL vs Red-Black often appears #

Rotations as a general technique #

Rotations aren’t only for BSTs. The broader pattern is:

You’ll see this in other data structures (e.g., B-trees have splits/merges; heaps have sift-up/down).

Performance summary #

If a balanced tree maintains height h = O(log n), then:

The “magic” is that the balancing work per operation is bounded by a constant number of rotations per violated node, and the number of visited nodes is proportional to the height.

In other words:

Time(operation) = O(height) = O(log n)

That guarantee is exactly why balanced trees are still a core part of CS—even in a world full of hash tables.

Worked Examples (3) #

AVL insertion requiring a single rotation (LL case) #

Insert keys in this order into an AVL tree: 30, 20, 10. Show how the AVL invariant is restored.

  1. Start with empty tree.

    Insert 30:

    • •Tree: 30
    • •height(30) = 0
    • •bf(30) = 0
  2. Insert 20 (BST rule: 20 < 30 so it goes left of 30):

    30

    /

    20

    Heights:

    • •height(20) = 0
    • •height(30) = 1 + max(0, −1) = 1

    Balance factors:

    • •bf(20) = 0
    • •bf(30) = height(left) − height(right) = 0 − (−1) = +1 (OK)
  3. Insert 10 (10 < 30, 10 < 20 → left of 20):

    30

    /

    20

    /

    10

    Heights bottom-up:

    • •height(10) = 0
    • •height(20) = 1 + max(0, −1) = 1
    • •height(30) = 1 + max(1, −1) = 2

    Balance factors:

    • •bf(20) = 0 − (−1) = +1 (OK)
    • •bf(30) = 1 − (−1) = +2 (violates AVL: must be in {−1,0,1})
  4. Classify the imbalance at node 30:

    • •Node 30 is left-heavy.
    • •The insertion was in the left subtree of its left child (30 → 20 → 10).

    This is the LL case.

  5. Fix with a right rotation at 30.

    Before (local):

    30

    /

    20

    /

    10

    After right rotation:

    20

    / \

    10 30

  6. Update heights:

    • •height(10) = 0
    • •height(30) = 0
    • •height(20) = 1 + max(0, 0) = 1

    Balance factors:

    • •bf(20) = 0 − 0 = 0
    • •bf(10) = 0
    • •bf(30) = 0

    AVL invariant restored.

Insight: A single rotation fixed a global-looking problem (the tree got tall) by repairing the first node whose local balance factor became ±2. That’s the core pattern of AVL rebalancing.

AVL insertion requiring a double rotation (LR case) #

Insert keys: 30, 10, 20 into an AVL tree. Show why a single rotation is not enough and how the LR double rotation works.

  1. Insert 30:

    • •Tree: 30
  2. Insert 10 (goes left of 30):

    30

    /

    10

    bf(30) = +1 (OK)

  3. Insert 20:

    • •20 < 30 so go left
    • •20 > 10 so go right of 10

    Tree:

    30

    /

    10

    \

    20

    Compute heights:

    • •height(20) = 0
    • •height(10) = 1 + max(−1, 0) = 1
    • •height(30) = 1 + max(1, −1) = 2

    Balance factors:

    • •bf(10) = (−1) − 0 = −1 (OK)
    • •bf(30) = 1 − (−1) = +2 (violates)
  4. Classify imbalance at 30:

    • •30 is left-heavy.
    • •But insertion happened in the right subtree of its left child (30 → 10 → 20).

    This is the LR case.

  5. Attempting a single right rotation at 30 would produce:

    10

    \

    30

    /

    20

    This still has imbalance because 30 becomes left-heavy (a zig-zag shape).

  6. Correct fix: double rotation

    Step 1: left rotate at node 10:

    Before:

    10

    \

    20

    After:

    20

    /

    10

  7. Step 2: right rotate at node 30 using new left child 20:

    Before (local):

    30

    /

    20

    /

    10

    After:

    20

    / \

    10 30

  8. Update heights:

    • •height(10) = 0
    • •height(30) = 0
    • •height(20) = 1

    All balance factors are 0, AVL invariant holds.

Insight: Double rotations resolve a zig-zag by first straightening the child subtree, then rotating the parent. Thinking in shapes (straight vs zig-zag) makes the cases easier to remember than memorizing LL/LR/RL/RR.

Red-Black height guarantee on a concrete tree #

Suppose a Red-Black tree has black-height bh = 4 at the root. Bound its height h and lower-bound the number of internal nodes n.

  1. Use the Red-Black property: no red node can have a red child.

    Therefore along any root→leaf path, red nodes can only appear between black nodes.

    So the maximum path length happens when you alternate colors:

    black, red, black, red, ...

  2. If the black-height is bh = 4, then there are 4 black nodes on each root→leaf path (by definition of black-height).

  3. Between consecutive black nodes, there can be at most 1 red node.

    So the number of red nodes on a longest path is at most 4 (or 3 depending on conventions), but the standard safe inequality is:

    h ≤ 2 · bh

  4. Plug in bh = 4:

    h ≤ 2 · 4 = 8

  5. Now lower-bound n from black-height.

    A subtree of black-height bh has at least 2ᵇʰ − 1 internal nodes.

    Reason: the minimum-node configuration is when all nodes are black and perfectly balanced, giving a perfect binary tree with bh levels of black nodes.

  6. Compute:

    2ᵇʰ − 1 = 2⁴ − 1 = 16 − 1 = 15

    So n ≥ 15

Insight: Red-Black trees control height indirectly: black-height forces exponential growth in nodes as bh increases, and the no-consecutive-red rule ensures height is at most twice bh.

Key Takeaways #

Common Mistakes #

Practice #

medium

AVL practice: Insert 10, 20, 30, 25 into an AVL tree (in that order). Draw the tree after each insertion and show which rotation(s) occur.

Hint: After inserting 30 you should see an RR imbalance at 10. After inserting 25, check balance factors on the path from 25 back to the root; look for a zig-zag.

Show solution

After 10,20,30:

Tree becomes:

20

/ \

10 30

Insert 25:

Tree:

20

/ \

10 30

/

25

Check bf:

No rotation needed.

easy

Rotation reasoning: Prove (by listing in-order sequences) that a right rotation preserves the BST in-order order for the involved nodes/subtrees.

Hint: Name the local parts: y as root, x = y.left, and β = x.right. Write in-order before and after using (subtree) placeholders.

Show solution

Before right rotation at y:

In-order is: (x.left), x, (β), y, (y.right).

After rotation, x becomes root, y becomes x.right, β becomes y.left.

In-order is: (x.left), x, (β), y, (y.right).

The sequences match, so BST order is preserved.

easy

Red-Black bound: If a Red-Black tree has n = 255 internal nodes, show that its height h is at most 16 using h ≤ 2 · log₂(n + 1).

Hint: Compute log₂(n + 1) with n + 1 = 256.

Show solution

n + 1 = 256.

log₂(256) = 8.

So h ≤ 2 · log₂(n + 1) = 2 · 8 = 16.

Connections #

Prerequisites: Binary Search Trees, Big O Notation

Next natural nodes: Heaps / Priority Queues, Hash Tables, B-Trees, Order Statistics Trees

Quality: A (4.4/5)

← back to treebrowse all →