A comparison sort decides the final order by comparing pairs of elements. Any such algorithm corresponds to a decision tree: each internal node is a comparison, each leaf is a final permutation. With possible permutations, the tree has at least leaves, so its height is at least .
What this means
Any algorithm whose only access to elements is comparisons must take comparisons in the worst case. Merge sort and heap sort hit this bound. Quicksort is on average but worst case.
When can you go faster?
If elements have additional structure — small integer keys, fixed-length strings, floats in a known range — you can use non-comparison sorts (counting sort, radix sort, bucket sort) and achieve linear time. The lower bound applies only to comparison-based methods.
In-place and stable
In-place sorts use or auxiliary space. Stable sorts preserve the relative order of equal elements — important when you sort by one key and want previous sort order preserved as a tiebreaker.
| Algorithm | Time (avg) | Time (worst) | Space | In-place | Stable | |-----------|-----------|--------------|-------|----------|--------| | Merge sort | | | | No | Yes | | Quicksort | | | | Yes | No | | Heap sort | | | | Yes | No | | Insertion sort | | | | Yes | Yes |
In practice
Production sort routines are typically hybrid — Timsort (Python's `sorted`, Java's Arrays.sort for objects) is a merge sort variant tuned for nearly-sorted real-world data. Introsort (C++ std::sort) starts with quicksort and falls back to heap sort if recursion depth gets too deep.