0
Comparisons
0
Swaps
0
Max Depth
0
Sorted
Ready
Status
Unsorted
Pivot
Left pointer (i)
Right pointer (j)
Active subarray
Sorted
⚡ Quicksort (current run)
Comparisons0
Swaps0
Time complexityO(n log n)
🫧 Bubble Sort (estimated)
Comparisons (est.)—
Swaps (est.)—
Time complexityO(n²)
How It Works
Quicksort is a divide-and-conquer algorithm. It picks a pivot, partitions the array so elements smaller than the pivot go left and larger go right, then recursively sorts each half.
Lomuto Partition Scheme
- Pick the last element as pivot
- Maintain a store index
i(left boundary of "greater than pivot" elements) - Scan from
lotohi-1with pointerj - If
arr[j] ≤ pivot, swaparr[i]andarr[j], incrementi - Finally place pivot at
i— it's now in its sorted position - Recurse on
[lo, i-1]and[i+1, hi]
Key Code (iterative with explicit stack)
function* quicksortGen(arr) {
const stack = [[0, arr.length - 1]]; // use stack to avoid true recursion
while (stack.length > 0) {
const [lo, hi] = stack.pop();
if (lo >= hi) continue;
// partition
const pivot = arr[hi];
let i = lo;
for (let j = lo; j < hi; j++) {
yield { type: 'compare', i, j, pivotIdx: hi, lo, hi };
if (arr[j] <= pivot) {
[arr[i], arr[j]] = [arr[j], arr[i]];
yield { type: 'swap', i, j };
i++;
}
}
[arr[i], arr[hi]] = [arr[hi], arr[i]]; // place pivot
yield { type: 'placed', pivotIdx: i };
stack.push([lo, i - 1]);
stack.push([i + 1, hi]);
}
}
Why It's Fast
On average, each partition splits the array roughly in half, giving O(n log n) total work. With n=40: Quicksort ≈ 40×6 = 240 ops, Bubble sort ≈ 40²/2 = 800 ops — 3× faster.
Complexity
Best Case
O(n log n)
Average Case
O(n log n)
Worst Case
O(n²)
Space
O(log n)
Stable?
No