Quick Sort
An in-place quicksort in TypeScript, with a note on why a left-side pivot forces right-to-left scanning.
published Mar 05, 2019 tags
#algorithms
#sorting
~/posts/quick-sort $ cat post.md
There are already plenty of quicksort writeups. This post just nails down a few details.
- One of quicksort’s selling points is in-place sorting. The variants that need extra space defeat the purpose.
- When the pivot is taken from the leftmost element, scanning must start from the right.
- Quicksort isn’t stable — duplicate elements can swap relative position.
Code
In-place quicksort in TypeScript:
const swap = <T>(arr: T[], left: number, right: number): void => {
const temp: T = arr[left];
arr[left] = arr[right];
arr[right] = temp;
};
const quickSort = <T>(
arr: T[],
left: number = 0,
right: number = arr.length - 1,
): void => {
if (left > right) {
return;
}
let lp: number = left;
let rp: number = right;
const pivot: T = arr[left]; // pivot from the left
while (lp != rp) {
// While pointers haven't met, scan right-to-left for the
// next value smaller than pivot.
while (lp < rp && arr[rp] >= pivot) {
rp--;
}
// Then scan left-to-right for the next value larger than
// pivot.
while (lp < rp && arr[lp] <= pivot) {
lp++;
}
// Swap them so the smaller side lands on the left.
if (lp < rp) {
swap(arr, lp, rp);
}
}
// Drop the pivot into its final spot.
arr[left] = arr[lp];
arr[lp] = pivot;
// Recurse on both sides.
quickSort(arr, left, lp - 1);
quickSort(arr, lp + 1, right);
};
Why scan from the right
Take 9 10 5 7.
- Pivot is the leftmost:
9. - Scan right-to-left for a value smaller than
9:7. - Scan left-to-right for a value larger than
9:10. Swap to get9 7 5 10. - Scan right-to-left for a value smaller than
9:5. - Scan left-to-right for a value larger than
9— the left pointer meets the right pointer at5. Swap pivot with the pointer position to get5 7 9 10. Done.
Step 4 is the punchline. If you scanned left-to-right first, the left
pointer would stop at 10. Swapping pivot to that slot would place a
larger value on the pivot’s spot and break the partition. Left pivot
forces right-first scanning; right pivot forces the reverse.