Sorting foundations
Before comparing individual algorithms, fix the vocabulary used to describe any sort: what is compared, in which direction, whether equal keys keep their order, how much extra memory is used, and whether existing order makes it faster.
Learning goals
- Define comparison sorting and write Comparators for keys and directions
- Explain stability and demonstrate it on duplicate keys
- Classify sorts as in-place or out-of-place and adaptive or not
Prerequisites
Comparison sorting
A comparison sort learns about the data only by asking “is a before b?”. Bubble, selection, insertion, merge, quick and heap sort are all comparison sorts.
Any comparison sort needs Ω(n log n) comparisons in the worst case (proved in Chapter 18). Counting, radix and bucket sort beat that bound because they inspect key values directly instead of comparing.
- Elementary sorts in this chapter are O(n²) but simple, in-place and fast for small n.
- Production sorts switch to insertion sort for small subarrays for exactly that reason.
Key comparison
You often sort records by one field, the key. In Java, Comparable defines a type's natural order, and a Comparator supplies any other order.
Never subtract to compare (a - b): it can overflow for large or negative values. Use Integer.compare or Comparator.comparingInt.
1record Student(String name, int grade, int age) {}23List<Student> list = new ArrayList<>(students);4list.sort(Comparator.comparingInt(Student::grade)); // key = grade5list.sort(Comparator.comparingInt(Student::grade)6.thenComparing(Student::name)); // tie-breaker78// Avoid: (a, b) -> a.grade() - b.grade() overflows for extreme values
Ascending/descending
Reversing the comparison reverses the order. Every algorithm on this page can sort descending by flipping > to <.
For primitive arrays, Arrays.sort(int[]) has no comparator, so sort ascending and then reverse, or box to Integer[] and use Comparator.reverseOrder().
1Integer[] boxed = {5, 1, 4};2Arrays.sort(boxed, Comparator.reverseOrder()); // [5, 4, 1]34list.sort(Comparator.comparingInt(Student::grade).reversed());
Stability
A sort is stable if records with equal keys stay in their original relative order. This matters when you sort by one key after another, for example by name and then by grade: a stable second sort keeps names ordered within each grade.
In the demo below, letters mark the original order of equal values. Stable sorts keep a before b; selection sort and shell sort can break it.
Stability: what happens to equal keys?
InteractiveInput · letters show original order of equal keys
Insertion sort
Bubble sort
Selection sort
Shell sort
In-place vs out-of-place
An in-place sort uses O(1) extra memory (or O(log n) for recursion) and rearranges the input itself. An out-of-place sort builds the result in a separate buffer.
All elementary sorts here are in-place. Merge sort is the classic out-of-place sort, with an O(n) buffer.
| In-place | Out-of-place |
|---|---|
| Bubble, selection, insertion, shell, heap, quick | Merge sort (array), counting sort, radix sort |
Adaptive sort
An adaptive sort runs faster when the input is already partly sorted. Insertion sort does work proportional to the number of inversions (pairs out of order), so nearly sorted input sorts in close to O(n).
Selection sort is not adaptive: it always scans the whole unsorted part to find the minimum.
Practice ladder
Now try it yourself
Easy
- Sort strings by length, then alphabetically
- Sort an int array in descending order
Medium
- Sort employees by department, then salary descending, using one comparator
- Prove a given sort is stable or produce a counterexample
Advanced
- Make any unstable sort stable by sorting (key, original index) pairs
- Count inversions to predict insertion sort's running time
Key takeaways
- Comparison sorts only use “is a before b?” and cannot beat Ω(n log n) in the worst case.
- Stability keeps equal keys in input order; it is essential for multi-key sorting.
- In-place means O(1) extra memory; adaptive means faster on nearly sorted input.