An efficient, in-place, comparison-based sorting algorithm. It applies the divide-and-conquer strategy. It works by selecting a 'pivot' element from the array and partitioning the other elements into two sub-arrays, according to whether they are less than or greater than the pivot. The sub-arrays are then sorted recursively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{
"arr": "[10, 7, 8, 9, 1, 5]",
"low": 0,
"high": 5
}Overview
Quick Sort picks one element as a pivot and partitions the array so that everything smaller than the pivot ends up on its left and everything else on its right. The pivot is then in its final position, and the two sides are sorted recursively.
The version on this page uses the Lomuto partition scheme with the last element as the pivot. Index i marks the end of the 'smaller than pivot' region; whenever arr[j] < pivot, that region grows by one and arr[j] is swapped into it. A final swap places the pivot just after the region.
With the default input 10, 7, 8, 9, 1, 5, the first pivot is 5: only 1 is smaller, so after partitioning the array becomes 1, 5, 8, 9, 10, 7, with 5 fixed at index 1.
Step by step
- Choose the pivot (
arr[high]here). - Set
i = low - 1; for eachjfromlowtohigh - 1, ifarr[j] < pivot, incrementiand swaparr[i]witharr[j]. - Swap the pivot into position
i + 1; this is its final index. - Recursively sort
low..iandi + 2..high. - Stop when a range has fewer than two elements.
Complexity
| Case | Cost | Why |
|---|---|---|
| Best case | O(n log n) | Each pivot splits its range roughly in half. |
| Average case | O(n log n) | Random pivots give balanced-enough splits on average. |
| Worst case | O(n^2) | With a last-element pivot, already-sorted input produces splits of size n-1 and 0 every time. |
| Extra space | O(log n) | Recursion stack for balanced splits; O(n) in the worst case. |
When to use it
- General-purpose in-memory sorting of arrays; its tight inner loop and cache-friendly access make it fast in practice.
- When stability is not required and extra O(n) memory for Merge Sort is unwanted.
- As the main engine of Intro Sort, which adds a fallback for the worst case.
Common mistakes
- A fixed first- or last-element pivot degrades to O(n^2) on sorted or reverse-sorted input. Median-of-three or a random pivot fixes this.
- Many duplicate keys also hurt Lomuto partitioning; three-way partitioning (Dutch national flag) handles them well.
- Recursing on the larger side first can overflow the stack; recurse on the smaller side and loop on the larger one.
A dry run is the best way to check your understanding of Quick Sort: follow each row, predict the next one, and compare. The run below takes 75 steps in total. Steps that only re-print loop counters are left out so the decisions stand out. The Line column refers to the line numbers in the code listing above.
- Input
- 10, 7, 8, 9, 1, 5
- Result
- return value = [1, 5, 7, 8, 9, 10]
| Step | Line | Array | What happens |
|---|---|---|---|
| 1 | 1 | [10, 7, 8, 9, 1, 5] | low = 0, high = 5 |
| 2 | 2 | [10, 7, 8, 9, 1, 5] | low = 0, high = 5, condition = 0 < 5 |
| 7 | 15 | [10, 7, 8, 9, 1, 5] | low = 0, high = 5, pivot = 5, i = -1, j = 0, condition = 10 < 5 |
| 9 | 15 | [10, 7, 8, 9, 1, 5] | low = 0, high = 5, pivot = 5, i = -1, j = 1, condition = 7 < 5 |
| 11 | 15 | [10, 7, 8, 9, 1, 5] | low = 0, high = 5, pivot = 5, i = -1, j = 2, condition = 8 < 5 |
| 13 | 15 | [10, 7, 8, 9, 1, 5] | low = 0, high = 5, pivot = 5, i = -1, j = 3, condition = 9 < 5 |
| 15 | 15 | [10, 7, 8, 9, 1, 5] | low = 0, high = 5, pivot = 5, i = -1, j = 4, condition = 1 < 5 |
| 17 | 17 | [1, 7, 8, 9, 10, 5] | low = 0, high = 5, pivot = 5, i = 0, j = 4 |
| 18 | 20 | [1, 5, 8, 9, 10, 7] | low = 0, high = 5, pivot = 5, i = 0 |
| 19 | 21 | [1, 5, 8, 9, 10, 7] | low = 0, high = 5, return value = 1 |
| 23 | 2 | [1, 5, 8, 9, 10, 7] | low = 0, high = 0, condition = 0 < 0 |
| 26 | 2 | [1, 5, 8, 9, 10, 7] | low = 2, high = 5, condition = 2 < 5 |
| 31 | 15 | [1, 5, 8, 9, 10, 7] | low = 2, high = 5, pivot = 7, i = 1, j = 2, condition = 8 < 7 |
| 33 | 15 | [1, 5, 8, 9, 10, 7] | low = 2, high = 5, pivot = 7, i = 1, j = 3, condition = 9 < 7 |
| 35 | 15 | [1, 5, 8, 9, 10, 7] | low = 2, high = 5, pivot = 7, i = 1, j = 4, condition = 10 < 7 |
| 36 | 20 | [1, 5, 7, 9, 10, 8] | low = 2, high = 5, pivot = 7, i = 1 |
| 37 | 21 | [1, 5, 7, 9, 10, 8] | low = 2, high = 5, return value = 2 |
| 41 | 2 | [1, 5, 7, 9, 10, 8] | low = 2, high = 1, condition = 2 < 1 |
| 44 | 2 | [1, 5, 7, 9, 10, 8] | low = 3, high = 5, condition = 3 < 5 |
| 49 | 15 | [1, 5, 7, 9, 10, 8] | low = 3, high = 5, pivot = 8, i = 2, j = 3, condition = 9 < 8 |
| 51 | 15 | [1, 5, 7, 9, 10, 8] | low = 3, high = 5, pivot = 8, i = 2, j = 4, condition = 10 < 8 |
| 52 | 20 | [1, 5, 7, 8, 10, 9] | low = 3, high = 5, pivot = 8, i = 2 |
| 53 | 21 | [1, 5, 7, 8, 10, 9] | low = 3, high = 5, return value = 3 |
| 57 | 2 | [1, 5, 7, 8, 10, 9] | low = 3, high = 2, condition = 3 < 2 |
| 60 | 2 | [1, 5, 7, 8, 10, 9] | low = 4, high = 5, condition = 4 < 5 |
| 65 | 15 | [1, 5, 7, 8, 10, 9] | low = 4, high = 5, pivot = 9, i = 3, j = 4, condition = 10 < 9 |
| 66 | 20 | [1, 5, 7, 8, 9, 10] | low = 4, high = 5, pivot = 9, i = 3 |
| 67 | 21 | [1, 5, 7, 8, 9, 10] | low = 4, high = 5, return value = 4 |
| 71 | 2 | [1, 5, 7, 8, 9, 10] | low = 4, high = 3, condition = 4 < 3 |
| 74 | 2 | [1, 5, 7, 8, 9, 10] | low = 5, high = 5, condition = 5 < 5 |
| 75 | 8 | [1, 5, 7, 8, 9, 10] | return value = [1, 5, 7, 8, 9, 10] |