"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)