DevTools Logo
All posts

Sorting Races, Maze Walkers and Self-Balancing Trees: Learning Algorithms by Watching Them Lose

August 26, 2026 · DevTools

algorithms
sorting
pathfinding
data structures
big o

Every algorithms course starts the same way: a table of Big-O bounds. O(n log n), O(n²), O(n·n!). The table is true, compact and almost useless for building intuition — because complexity is a statement about growth, and human intuition is about behavior. The fastest way to close that gap is to watch two algorithms attack the same input and lose differently.

The race that teaches partitioning

Put QuickSort (Lomuto partition) and MergeSort in parallel lanes on the same array and press play. On random data they finish close together. Now feed both lanes an already-sorted array: MergeSort glides through its usual halving rhythm while QuickSort visibly degrades — every partition splits 0 / n−1, the recursion dives one element at a time, and the comparison counter balloons. That's the O(n²) worst case happening in front of you, not in a footnote. It also explains why the fixes work: a random pivot or Hoare's two-cursor partition breaks the pattern, and you can race those variants to see the difference.

Racing also settles arguments the table can't. At 16 elements, InsertionSort routinely beats MergeSort on operation count — its constant factors win until n log n's advantage kicks in around 30–50 elements. Engineers who internalize this stop reflexively reaching for the "faster" asymptotic winner at small n, which is most of the arrays in a real codebase.

Pathfinding: three frontier shapes

Switch arenas and the same idea applies to graphs on a grid. BFS's frontier ripples outward in tidy rings; DFS dives down the first corridor and smears visited cells across the map; A* with a Manhattan heuristic carves a focused ellipse toward the goal. Same maze, same seed — radically different search shapes. The visited-cell counter makes the difference concrete: A* on a typical maze touches a fraction of the cells BFS does, and still returns an optimal path because Manhattan distance never overestimates on a 4-neighbour grid. Greedy Best-First looks even leaner until it returns a path that's provably longer, which is exactly the lesson: heuristics buy speed, admissibility buys optimality, and you need to know which one you're spending.

Trees that heal themselves

Balanced trees are the classic "understood in theory, unexplainable at a whiteboard" topic. Replay AVL insertions with the tree redrawn after every operation and rotations stop being incantations: you watch a node's balance factor hit ±2, see the RR case fire, and see the subtree pivot — the log spells out imbalance +2 at 30 → LL rotation. Red-Black trees become readable too, once recoloring and rotation are separate, visible steps instead of a wall of case analysis. Even B-trees — the structure behind every database index — demystify quickly when you watch a node overflow and promote its median to the parent.

Sound, steps and source

Two extras turn watching into learning. Step replay with scrubbing means you can stop mid-partition, look at exactly which elements were compared, and think before continuing — backward scrubbing is even better for "wait, why did it swap there?" moments. And sonification — mapping compared values to pitch — sounds like a gimmick until you hear BubbleSort's rising arpeggios versus QuickSort's register-jumping partition sweeps; your ears parse access patterns your eyes gloss over.

Finally, the visual only earns trust if it connects to real code. A good visualizer highlights the line of the reference implementation that's executing — in whatever language you actually ship — so every colored bar maps to a statement you can copy. Theory, behavior and implementation, reconciled in one screen.

That's the whole philosophy: complexity tables tell you what to expect; stepping the engine shows you why. Race your favorites, break them with adversarial input, and the bounds stop being trivia — they become predictions you can verify in ten seconds.