"There's a proven speed limit for sorting by comparisons — and then there's the sneaky way around it: stop comparing. This lesson is about the wall, the sort you actually use that lives at the wall, and the sorts that tunnel under it."
The Wall: Why O(n log n) Is a Hard Limit
Any sort that works by comparing elements has a proven floor: O(n log n). The argument is elegant. There are n! possible orderings of n items, and a sort must be able to land on whichever one is correct. Each comparison is a single yes/no question — one branch of a decision tree. To have enough leaves to distinguish all n! outcomes, the tree must be at least log₂(n!) ≈ n log n deep. So no comparison sort — not quicksort, not merge sort, not any future clever one — can beat O(n log n) in the worst case. It's not a failure of imagination; it's a mathematical limit.
Timsort: the Sort You Actually Use
Python's sorted() and list.sort() use Timsort (also Java's default for objects). It's a hybrid: merge sort's structure, insertion sort for small runs, plus a brilliant trick — it detects existing sorted runs in the data and merges them, instead of starting from scratch. Real-world data is frequently partly-sorted (timestamps, appended logs, mostly-ordered records), so Timsort often runs far better than its O(n log n) worst case — approaching O(n) on nearly-sorted input. It's also stable. It sits right at the comparison-sort wall in the worst case, but is adaptive and fast in the common case, which is why it's the production default.
Tunneling Under the Wall: Non-Comparison Sorts
The lower bound only binds sorts that compare. Sorts that exploit structure in the keys escape it entirely:
- Counting sort: if keys are integers in a small range [0, k], just count how many of each value, then emit them in order. O(n + k) — linear, no comparisons. Brilliant for small-integer keys (ages, grades, byte values).
- Radix sort: sort by digit/character, least-significant first, using counting sort per digit. O(d·n) for d-digit keys. It's how you sort huge sets of fixed-width keys (IDs, strings) faster than n log n.
The deep lesson: the O(n log n) wall is a property of the comparison model, not of sorting itself. Change the assumptions — assume small-integer keys, exploit their structure — and the limit changes with them. Reframing what you're allowed to assume is how barriers fall.