← System Design Simulator

Red-Black Tree Visualization for Coding Interviews

By Rahul Kumar · Senior Software Engineer · Updated · Category: Trees

Recolor + rotate cases; every path has equal black-height.

Concept

A red-black tree is a binary search tree that tags every node with a color - red or black - and enforces five invariants so that the longest root-to-leaf path is at most twice the length of the shortest. That looser bound compared to AVL means lookups are slightly slower, but the amortized number of rotations per update is smaller, which is why red-black trees underlie Java's TreeMap, C++ std::map, and the Linux kernel's CFS scheduler. The five CLRS invariants are: every node is red or black; the root is black; every NIL leaf is black; no red node has a red child; every root-to-leaf path has the same number of black nodes (the black-height). The last two together imply the 2x height bound. Most implementations use a shared sentinel NIL node to stand in for every null child, which simplifies color bookkeeping because NIL is always black and you never have to null-check before reading a color.

Red-Black Tree — Interactive Simulator

Runs fully client-side in your browser; no sign-up. Or open full screen →

Launch the interactive Red-Black Tree visualization — animated algorithm, step-through, and live data-structure updates.

How it works

Insert starts with a plain BST insert and colors the new node red, because coloring it black would immediately violate the equal-black-height property. The only invariant that can now be broken is the no-red-red rule. Fix-up walks up from the new node and handles three cases by looking at the uncle (the sibling of the parent). Case 1: the uncle is red - recolor parent and uncle to black, recolor grandparent to red, then move the pointer up to the grandparent and repeat. Case 2: the uncle is black and the new node is the inner child (left-right or right-left shape) - rotate the parent to convert it into case 3. Case 3: the uncle is black and the new node is the outer child - recolor parent to black, grandparent to red, and rotate the grandparent. Delete is structurally similar but harder, because removing a black node reduces the black-height of one subtree. The fix-up pushes a conceptual extra-black token up the tree and eliminates it via four mirrored cases that look at the sibling's color and the colors of the sibling's children. All operations run in O(log n) with at most three rotations per insert and four per delete, which is why red-black is the default balanced BST in most standard libraries.

Implementation

Red-black tree insert with CLRS fix-up and NIL sentinel
public class RedBlackTree {
    private static final boolean RED = true, BLACK = false;

    static class RBNode {
        int key;
        boolean color;
        RBNode left, right, parent;
        RBNode(int key, boolean color) { this.key = key; this.color = color; }
    }

    private final RBNode NIL = new RBNode(0, BLACK);
    private RBNode root = NIL;

    public void insert(int key) {
        RBNode z = new RBNode(key, RED);
        z.left = z.right = z.parent = NIL;
        RBNode y = NIL, x = root;
        while (x != NIL) { y = x; x = key < x.key ? x.left : x.right; }
        z.parent = y;
        if (y == NIL) root = z;
        else if (key < y.key) y.left = z; else y.right = z;
        insertFixUp(z);
    }

    private void insertFixUp(RBNode z) {
        while (z.parent.color == RED) {
            RBNode g = z.parent.parent;
            if (z.parent == g.left) {
                RBNode y = g.right;                   // uncle
                if (y.color == RED) {                 // case 1: recolor
                    z.parent.color = BLACK; y.color = BLACK; g.color = RED; z = g;
                } else {
                    if (z == z.parent.right) { z = z.parent; leftRotate(z); }  // case 2
                    z.parent.color = BLACK; z.parent.parent.color = RED;        // case 3
                    rightRotate(z.parent.parent);
                }
            } else {
                RBNode y = g.left;
                if (y.color == RED) {
                    z.parent.color = BLACK; y.color = BLACK; g.color = RED; z = g;
                } else {
                    if (z == z.parent.left) { z = z.parent; rightRotate(z); }
                    z.parent.color = BLACK; z.parent.parent.color = RED;
                    leftRotate(z.parent.parent);
                }
            }
        }
        root.color = BLACK;
    }

    private void leftRotate(RBNode x) {
        RBNode y = x.right;
        x.right = y.left;
        if (y.left != NIL) y.left.parent = x;
        y.parent = x.parent;
        if (x.parent == NIL) root = y;
        else if (x == x.parent.left) x.parent.left = y; else x.parent.right = y;
        y.left = x; x.parent = y;
    }

    private void rightRotate(RBNode y) {
        RBNode x = y.left;
        y.left = x.right;
        if (x.right != NIL) x.right.parent = y;
        x.parent = y.parent;
        if (y.parent == NIL) root = x;
        else if (y == y.parent.right) y.parent.right = x; else y.parent.left = x;
        x.right = y; y.parent = x;
    }
}

Complexity

Common pitfalls

Key design decisions & trade-offs

Practice problems

Interview follow-ups

Why it matters

Red-Black Tree is a core part of the Trees toolkit. If you are preparing for a technical interview at a top-tier company or teaching a course, a working visualization is the fastest path from "I read about it" to "I understand it".

Related