Quick sort
Take the last item as the pivot, move smaller items to its left and larger ones to its right, then sort each side recursively.
Quick sort is also "divide and conquer", but it does the main work before recursing:
Read the full explanation ↓- Time:
O(n log n) on average, O(n²) at worst - Space:
O(log n) stack on average - CLRS, section 7.1
- Horowitz–Sahni, chapter 7
Eight mixed numbers with 4 as the first pivot; 15 comparisons.
def quick_sort(a):sort(a, 0, len(a) - 1)return adef sort(a, lo, hi):if lo >= hi:returnp = partition(a, lo, hi)sort(a, lo, p - 1)sort(a, p + 1, hi)def partition(a, lo, hi):pivot = a[hi]i = lo - 1for j in range(lo, hi):if a[j] <= pivot:i = i + 1a[i], a[j] = a[j], a[i]a[i + 1], a[hi] = a[hi], a[i + 1]return i + 1
Start
Recursion tree
Filled orange = running call · Orange outline = still on the stack · Grey = finished
Local variables
Orange = changed in this step
a list
28713564
Call stack
- quick_sort()line 1
Step 1 of 124
How the work grows with input size
Average of 12 random graphs per n (fixed seeds). Hollow marker = the input on screen.
- comparisons
- swaps
- place
- current input (n=8)
Show as a table
| n | comparisons | swaps | place |
|---|---|---|---|
| 4 | 4.7 | 2.5 | 2.3 |
| 6 | 9.8 | 4.4 | 3.6 |
| 8 | 17.4 | 8.3 | 5.1 |
| 10 | 25.5 | 14.2 | 6.6 |
| 12 | 32.4 | 17.8 | 7.5 |
| 14 | 41.3 | 24.3 | 8.8 |
| 16 | 52.5 | 29.2 | 10.6 |
Explanation
The idea
Quick sort is also "divide and conquer", but it does the main work before recursing:
- Pick a pivot; here it is the last item of the range,
a[hi]. - Partition the range: items
≤ pivotgo left, the rest go right, and the pivot lands between them in its final place. - Sort both sides of the pivot recursively. No combining is needed, because the array is sorted in place.
Partitioning (Lomuto's scheme)
i marks the end of the "small" part. j walks from lo to hi − 1; whenever a[j] ≤ pivot, i moves up one and
a[i] and a[j] are swapped. At the end, the pivot is swapped with a[i + 1].
Cost
- If each pivot splits its range roughly in half, the recursion is
log ndeep and the time isO(n log n). This is also the average case. - If the pivot is always the largest or smallest item (for example on a sorted array), one side stays empty and
the time becomes
O(n²). - Repeated items also give unbalanced splits with this scheme; see the "all equal" input.
- A random pivot makes the bad case unlikely, but here the pivot is fixed (the last item) so every run is the same.
What to watch in the trace
pivotis written above the array and the blue band is the rangelo..hi. Theiandjarrows are the borders of the partition.- In the "recursion tree", compare the shape for the best case and the worst case: one wide and short, the other a long chain.