From bubble sort's O(n²) simplicity to merge sort's O(n log n) guarantee — how ordering data unlocks everything else.
Simple sorts (bubble, selection, insertion) compare neighbors and run in O(n²) — fine for tiny or nearly-sorted inputs. Efficient sorts divide and conquer: merge sort always runs in O(n log n) and is stable; quicksort averages O(n log n) with better constants but O(n²) worst case. O(n log n) is provably optimal for comparison-based sorting, and real libraries ship hybrids like Timsort.
Step through sorting algorithms live, one move at a time — this becomes a fully interactive visualizer.
Coming soonfunction mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = arr.length >> 1;
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
const out = [];
let i = 0, j = 0;
while (i < left.length && j < right.length) {
out.push(left[i] <= right[j] ? left[i++] : right[j++]);
}
return [...out, ...left.slice(i), ...right.slice(j)];
}Its average case has excellent constants: in-place partitioning, sequential memory access, no allocation. Randomized or median-of-three pivots make the worst case astronomically unlikely on real data.
A stable sort preserves the relative order of equal elements. It matters when you sort by one key after another — sort by name, then stably by department, and names stay alphabetical within each department.
They never compare elements — they bucket by digit or value directly, running in O(n + k). The Ω(n log n) bound only applies to sorts that learn order through comparisons.
Share what clicked for you and see notes from other learners on this topic.
Coming soon