
Sorting Algorithms Explained
Big-O, stability, memory trade-offs, and practical cutoffs for production systems.
Quick picks
- General backend arrays in Python: use built-in list.sort() or sorted() first.
- Need guaranteed O(n log n) and stable ordering: prefer merge-sort style behavior.
- Memory constrained environment: evaluate in-place strategies such as heapsort variants.
- Tiny or nearly sorted lists: insertion-sort behavior can be very efficient.
Complexity Cheat Sheet
| Algorithm | Best | Average | Worst | Extra Space | Stable | Best When |
|---|---|---|---|---|---|---|
| Timsort (Python built-in) | O(n) | O(n log n) | O(n log n) | O(n) | ✅ | General-purpose production sorting |
| Quicksort | O(n log n) | O(n log n) | O(n^2) | O(log n) | ❌ | Fast in practice with good pivots |
| Mergesort | O(n log n) | O(n log n) | O(n log n) | O(n) | ✅ | Stable output and predictable runtime |
| Heapsort | O(n log n) | O(n log n) | O(n log n) | O(1) | ❌ | When memory is tight and worst-case matters |
| Insertion Sort | O(n) | O(n^2) | O(n^2) | O(1) | ✅ | Small or almost-sorted arrays |
| Selection Sort | O(n^2) | O(n^2) | O(n^2) | O(1) | ❌ | Teaching and constrained swap-count scenarios |
Workload-to-Algorithm Mapping
| Workload Pattern | Recommended Default | Reason |
|---|---|---|
| API list endpoints with secondary tie-breakers | Built-in stable sort | Preserves deterministic ordering across equal keys |
| Large unsorted batch jobs | Built-in sort or tuned mergesort | Predictable throughput and strong real-world performance |
| Memory-constrained processing | Heapsort-style approach | Low additional memory usage |
| Small nearly sorted arrays | Insertion-friendly behavior | Very low overhead on short or nearly sorted input |
| Latency-sensitive deterministic systems | Stable O(n log n) strategy | Avoid worst-case spikes |
benchmark_sorting.py
FAQ
Quick Rule
Start with the built-in sort, then optimize only where profiling shows a bottleneck.