Red-Black Trees: How Self-Balancing Search Trees Guarantee Logarithmic Height

The plain binary search tree covered earlier in this series can degrade to linear height under unlucky insertion orders. Red-black trees solve this by maintaining five simple invariants that mathematically guarantee logarithmic height regardless of insertion order. This comprehensive guide covers the red-black properties, the rotation operation that preserves the search-tree structure while restructuring the tree, and how insertion and deletion are extended with rebalancing logic to maintain these guarantees.

Red-Black TreeTree RotationSelf-Balancing Tree

~7 دقیقه مطالعه · آخرین به‌روزرسانی ۱۶ شهریور ۱۴۰۵

Why Plain Binary Search Trees Are Not Enough

As discussed earlier in this series, a plain binary search tree's every operation runs in O(h) time, where h is the tree's height. The problem is that h can grow as large as Θ(n) under certain insertion orders, such as inserting already-sorted data, degrading every operation to linear time. A Red-Black Tree solves this by adding extra structure that mathematically guarantees h = O(log n) at all times, regardless of the order of insertions and deletions.

The Five Red-Black Properties

A red-black tree is a binary search tree, using the exact same underlying node structure introduced earlier in this series, with one extra attribute per node: a Color, either red or black. A binary search tree qualifies as a valid red-black tree if and only if it satisfies all five of these properties:

1. Every node is either red or black.
2. The root is always black.
3. Every leaf (represented as NIL) is black.
4. If a node is red, both of its children are black.
   (No two red nodes can appear consecutively on any path.)
5. For each node, all simple paths from that node down to
   descendant leaves contain the same number of black nodes.
   (This count is called the node's Black-Height.)

Why These Properties Guarantee Logarithmic Height

Property 4 ensures no path can have two consecutive red nodes, and property 5 ensures every path from a given node has exactly the same number of black nodes. Together, these properties bound how much longer the longest path can be compared to the shortest path from the root: the longest possible path alternates red and black nodes, at most doubling the length of the shortest possible path, which consists of only black nodes.

Key theorem: a red-black tree with n internal nodes
has height at most 2·log₂(n+1)

Proof sketch: the subtree rooted at any node x has at
least 2^(bh(x)) - 1 internal nodes, where bh(x) is the
black-height of x. Applying this at the root, combined
with the fact that at least half the nodes on any path
from root to leaf must be black (property 4), yields
the O(log n) height bound.

This mathematical guarantee is what makes red-black trees reliable: no matter what sequence of insertions and deletions occurs, the tree's height never exceeds O(log n), ensuring every search-tree operation discussed earlier in this series — search, minimum, maximum, successor, insertion, and deletion — runs in guaranteed O(log n) time.

Rotations: Restructuring While Preserving Order

Maintaining the red-black properties during insertion and deletion requires a structural operation called Rotation, which changes the local pointer structure of the tree, but preserves the binary-search-tree property discussed earlier in this series.

LEFT-ROTATE(T, x):
  y = x.right
  x.right = y.left
  if y.left ≠ NIL:
      y.left.p = x
  y.p = x.p
  if x.p == NIL:
      T.root = y
  elif x == x.p.left:
      x.p.left = y
  else:
      x.p.right = y
  y.left = x
  x.p = y

Before LEFT-ROTATE(x):        After LEFT-ROTATE(x):
        x                              y
       / \                            / \
      a   y          -->             x   c
         / \                        / \
        b   c                      a   b

RIGHT-ROTATE is the exact mirror image. Crucially, a rotation runs in O(1) time, since it only involves updating a constant number of pointers, and it never violates the binary-search-tree property — the relative order of all elements remains exactly the same, only the tree's shape changes.

Insertion: Color, Then Fix

Insertion into a red-black tree starts with the ordinary binary-search-tree insertion procedure covered earlier in this series, with the new node initially colored red. Coloring the new node red is a deliberate choice: it cannot violate property 5 (the black-height property), since a red node adds nothing to any path's black count, but it might violate property 4 if the new node's parent is also red.

RB-INSERT-FIXUP(T, z):
  while z.p.color == RED:
      if z.p == z.p.p.left:
          y = z.p.p.right   // z's uncle
          if y.color == RED:
              // Case 1: uncle is red — recolor and move up
              z.p.color = BLACK
              y.color = BLACK
              z.p.p.color = RED
              z = z.p.p
          else:
              if z == z.p.right:
                  // Case 2: uncle is black, z is a right child
                  z = z.p
                  LEFT-ROTATE(T, z)
              // Case 3: uncle is black, z is a left child
              z.p.color = BLACK
              z.p.p.color = RED
              RIGHT-ROTATE(T, z.p.p)
      else:
          (symmetric cases, with left and right swapped)
  T.root.color = BLACK

The fixup procedure handles three distinct cases based on the color of the newly inserted node's uncle. When the uncle is red, the violation can be resolved purely by recoloring and moving the problem up toward the root. When the uncle is black, one or two rotations combined with recoloring permanently resolve the violation without needing to continue upward. Since each iteration either terminates or moves up one level, and rotations happen at most twice, the entire fixup procedure runs in O(log n) time, matching the tree's height.

Deletion: The Most Involved Operation

Deletion follows the same basic transplant-based approach as ordinary binary-search-tree deletion, discussed earlier in this series, but requires careful handling when a black node is removed, since this could violate the black-height property for paths that used to pass through it.

The technique introduces a conceptual Extra Black on the node that takes the deleted node's place, temporarily allowing a violation, which the fixup procedure then resolves through a combination of recoloring and rotations, handled through four distinct cases depending on the color and structure of the deleted node's sibling.

The four cases in RB-DELETE-FIXUP, at a high level:
Case 1: sibling is red             → rotate and recolor, reduce to case 2/3/4
Case 2: sibling is black with
        two black children         → recolor sibling, move problem up
Case 3: sibling is black with a
        near black child, far red  → rotate sibling, reduce to case 4
Case 4: sibling is black with a
        far red child              → rotate and recolor, done

Despite its intricacy, this fixup procedure also runs in O(log n) time, since it performs at most a constant number of rotations and moves up the tree at most O(log n) times before terminating.

Why Red-Black Trees Are the Standard Self-Balancing Tree

Red-black trees strike a practical balance between rebalancing overhead and guaranteed performance. Compared to other self-balancing schemes like AVL trees, red-black trees require fewer rotations on average per insertion or deletion, since their balance condition is somewhat looser (allowing the longest path to be up to twice the shortest, rather than requiring near-perfect balance), while still guaranteeing the same O(log n) worst-case height. This favorable trade-off between rebalancing cost and height guarantee is why red-black trees are used in many real-world systems, including the standard library implementations of ordered maps and sets in numerous programming languages, and even in the Linux kernel's process

نوشته و پژوهش‌شده توسط دکتر شاهین صیامی

مقالات مرتبط

Number-Theoretic Algorithms: GCD, Modular Exponentiation, and RSA

Modern cryptography and countless algorithmic applications rely on a handful of elegant number-theoretic algorithms. This comprehensive guide covers Euclid's algorithm for computing the greatest common divisor, fast modular exponentiation for efficiently computing large powers, and the mathematical foundation of RSA encryption, one of the most widely deployed cryptographic systems in the world.

ادامه

Computational Geometry Basics: Orientation, Line Intersection, and Convex Hull

Geometric algorithms solve problems involving points, lines, and shapes, appearing in computer graphics, robotics path planning, and geographic information systems. This comprehensive guide covers the cross-product-based orientation test that underlies nearly every geometric algorithm, segment intersection detection built on that test, and Graham's scan algorithm for computing the convex hull of a set of points.

ادامه

String Matching Algorithms: Naive Search, Rabin-Karp, and Beyond

Searching for a pattern within a larger text is one of the most common operations in computing, from text editors to DNA sequence analysis. This comprehensive guide covers the naive string-matching algorithm and its quadratic worst case, then explains the Rabin-Karp algorithm's clever use of hashing to achieve fast average-case performance, including how it handles hash collisions correctly.

ادامه

Approximation Algorithms: Getting Provably Close to Optimal for Hard Problems

When a problem is proven NP-complete, an exact efficient solution is unlikely to exist, but that does not mean giving up on the problem entirely. This comprehensive guide explains approximation algorithms, which sacrifice guaranteed optimality for guaranteed efficiency, covering the vertex cover and traveling salesman problems as classic examples with provable approximation ratios.

ادامه

NP-Completeness Explained: P, NP, and Why Some Problems Resist Efficient Solutions

Some problems have resisted every attempt at an efficient algorithm for decades, yet no one has proven an efficient solution is impossible. This comprehensive guide explains the classes P and NP, the concept of polynomial-time reductions used to compare problem difficulty, and how proving a problem NP-complete provides strong evidence, though not proof, that no efficient algorithm exists.

ادامه

Maximum Flow: Ford-Fulkerson and the Min-Cut Max-Flow Theorem

Maximum flow problems model the largest possible throughput through a network with capacity-limited connections, from water pipes to data networks. This comprehensive guide introduces flow networks, walks through the Ford-Fulkerson method for finding maximum flow using augmenting paths, and explains the elegant min-cut max-flow theorem that connects two seemingly different problems into one.

ادامه