A Note on Quicksort Partitioning
Partitioning is the core operation of quicksort. Two classical schemes exist: Hoare’s [1] and Lomuto’s. The expected-case analysis of the overall algorithm is due to Sedgewick [2].
Given an array and a pivot , partitioning rearranges values so every element to the left of some index satisfies and every element to the right satisfies .
A function partition(a, lo, hi) rearranges so that there
exists an index where for and
for , and returns .
For any input array of size , Hoare’s partition performs at most comparisons in the worst case.
The left and right pointers advance monotonically and meet in steps. A tight bookkeeping argument shows the total number of comparisons is bounded by in the worst case, attained when the pivot lands near a quarter-point.
The following TypeScript implementation mirrors Hoare’s original scheme, with two pointers converging inward and swap() exchanging
out-of-place elements:
// Hoare-style partition
function partition(arr: number[], lo: number, hi: number): number {
const pivot = arr[lo];
let i = lo - 1;
let j = hi + 1;
while (true) {
do {
i++;
} while (arr[i] < pivot);
do {
j--;
} while (arr[j] > pivot);
if (i >= j) return j;
[arr[i], arr[j]] = [arr[j], arr[i]];
}
}
Calling partition(arr, lo, hi) returns the split index. An unbalanced pivot degrades quicksort to ; randomising the pivot
restores expected .