DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on • Originally published at github.com

I built a sorting visualizer that counts every comparison and swap, so Big-O stops being abstract

"Bubble sort is O(n²), merge sort is O(n log n)" is one of those facts everyone memorizes and few people feel. So I built a visualizer that doesn't just animate the bars — it counts every comparison and every write, so the difference between the two complexity classes shows up as a number and as how long the animation runs.

▶ Live demo: https://dev48v.github.io/sorting-visualizer/
Source: https://github.com/dev48v/sorting-visualizer

Six algorithms, same array, colour-coded operations: 🟡 comparing, 🔴 writing/swapping, 🟢 locked in place.

The counts make the theory concrete

Run each algorithm on a size-40 array and the comparison counts come out roughly like this:

Algorithm Comparisons (n=40) Class
Selection 780 Θ(n²)
Bubble ~770 Θ(n²)
Insertion ~470 Θ(n²), less on lucky input
Heapsort ~305 Θ(n log n)
Quicksort ~210 Θ(n log n)
Merge ~160 Θ(n log n)

Selection sort's 780 is not a coincidence — it's exactly n(n-1)/2 = 40·39/2. It compares every pair regardless of the data, which is why its best case and worst case are identical. Merge sort does about a fifth of the comparisons. Bump the size to 100 and the gap widens fast — that's the n² vs n log n curve, in operations you can count.

What each animation reveals

  • Bubble — the largest unsorted element "bubbles" to the end each pass; you watch the green sorted region grow from the right.
  • Insertion — each element walks left into place. On a nearly-sorted array it barely moves: its best case really is O(n).
  • Selection — scans for the minimum, one swap per pass. Almost no writes (great when writes are expensive) but always ~n²/2 comparisons.
  • Quicksort — pick a pivot, partition everything smaller to its left, then recurse into each side. Watch the pivot snap to its final position (green) and the two halves get solved independently.
  • Merge — splits down to singletons, then merges sorted runs back up. It uses O(n) extra space (the writes you see are copies back from a temp buffer) but never degrades to O(n²).
  • Heapsort — builds a max-heap, then repeatedly swaps the root to the end and sifts down. O(1) extra space and O(n log n) worst case.

A note on how it's built

The animation and the algorithm are decoupled. Each sort runs on a copy of the array and emits a list of operations — compare(i,j), swap(i,j), set(i,value), markSorted(i). The visualizer then replays that list at whatever speed you pick. This keeps the algorithms readable (they're just normal sorts with instrumented compare/swap), makes the counts exact, and means "stop" and "speed" are trivial — you're just pausing or fast-forwarding a tape.

Sort a big array with Bubble, then with Quick, and watch the comparison counter. Once you've seen 780 vs 160 on the same input, the Big-O notation stops being abstract.

If it helped, a star helps others find it: https://github.com/dev48v/sorting-visualizer

Top comments (0)