Randomized Quick Sort: Mechanism, Complexity Analysis & Interactive Visualizer
Randomized Quick Sort
Pick the pivot uniformly at random. The expected runtime is O(n log n) on every input — no adversary can construct a bad case.
How it works
Plain Quick Sort hits O(n²) when the pivot consistently splits the array unevenly. With a fixed pivot policy (e.g., "always pick the last element"), an attacker — or just unlucky input like an already-sorted array — can guarantee that worst case.
Randomized Quick Sort eliminates that problem with one line of code: swap a random element in the current range to the pivot position before partitioning.
- Choose a random index
r ∈ [lo, hi]. - Swap
arr[r]witharr[hi]. - Proceed with the normal Lomuto partition.
Each partition's expected balance is now over a uniformly random pivot, regardless of input. The result: expected O(n log n) runtime on every input, with a negligible probability of pathological recursion.
Complexity
Interactive visualization
Pseudocode
procedure randomizedQuickSort(A, lo, hi): if lo < hi: r ← random integer in [lo, hi] swap A[r], A[hi] p ← partition(A, lo, hi) randomizedQuickSort(A, lo, p − 1) randomizedQuickSort(A, p + 1, hi)
JavaScript implementation
function randomizedQuickSort(arr, lo = 0, hi = arr.length - 1) { if (lo < hi) { const r = lo + Math.floor(Math.random() * (hi - lo + 1)); [arr[r], arr[hi]] = [arr[hi], arr[r]]; const p = partition(arr, lo, hi); randomizedQuickSort(arr, lo, p - 1); randomizedQuickSort(arr, p + 1, hi); } return arr; } function partition(arr, lo, hi) { const pivot = arr[hi]; let i = lo - 1; for (let j = lo; j < hi; j++) { if (arr[j] <= pivot) { i++; [arr[i], arr[j]] = [arr[j], arr[i]]; } } [arr[i + 1], arr[hi]] = [arr[hi], arr[i + 1]]; return i + 1; }
Pros and cons
Pros
- Expected O(n log n) on every input — no worst-case input exists.
- Trivially small code change over plain Quick Sort.
- Defeats adversarial attacks like algorithmic complexity DoS.
- Preserves all of Quick Sort's practical advantages.
Cons
- Still not stable.
- Worst-case bound is unchanged in theory — only the expected case improves.
- Requires a usable PRNG; in security-sensitive contexts you'd want a tamper-resistant source.
When to use it
- Default Quick Sort implementation in almost every standard library.
- User-supplied input where an attacker might construct worst-case data.
- Database query engines sorting on indexed columns.
Related reading
Sleep Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A unique concurrency-based sorting algorithm: spawns a separate thread for each element, sleeping for a duration proportional to the element value before writing it to the output.
By Md. Harun-Or-Roshid
Cube Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A parallel dimension sorting algorithm: organizes elements in a 3D coordinate cube and sorts vectors along the height, width, and depth axes sequentially to achieve sorted order.
By Md. Harun-Or-Roshid
Patience Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A card-game inspired sorting algorithm: distributes elements onto a series of piles such that each pile's top is \(\ge\) the incoming value, then performs a multi-way merge across pile tops.
By Md. Harun-Or-Roshid
Library Sort: Mechanism, Complexity Analysis & Interactive Visualizer
A gapped variation of Insertion Sort: leaves empty slots (gaps) in the array, allowing elements to be inserted in \(O(1)\) shift time on average by avoiding massive shifts.
By Md. Harun-Or-Roshid