Stable Quicksort

Quicksort that preserves the order of equal elements by partitioning each range into less / equal / greater buffers and writing them straight back, so every level visibly regroups the bars in place. The equal block lands in its final position immediately.

Best O(n log n) Avg O(n log n) Worst O(n²) Space O(n) Stable Yes In-place No Comparison-based

How it works

Quicksort that preserves the order of equal elements by partitioning each range into less / equal / greater buffers and writing them straight back, so every level visibly regroups the bars in place. The equal block lands in its final position immediately.

Implementation

function stableQuickSort(arr, stats) {
  const n = arr.length;
  if (n < 2) return;
  const temp = new Array(n).fill(0);
  const stackLo = new Array(n + 1).fill(0);
  const stackHi = new Array(n + 1).fill(0);
  let top = 0;
  stackLo[top] = 0;
  stackHi[top] = n - 1;
  top++;
  while (top > 0) {
    top--;
    const lo = stackLo[top];
    const hi = stackHi[top];
    if (lo >= hi) continue;
    const pivot = arr[(lo + hi) >> 1];
    let t = lo;
    for (let i = lo; i <= hi; i++) {
      if (arr[i] < pivot) {
        temp[t] = arr[i];
        t++;
      }
    }
    const ltEnd = t;
    for (let i = lo; i <= hi; i++) {
      if (arr[i] === pivot) {
        temp[t] = arr[i];
        t++;
      }
    }
    const eqEnd = t;
    for (let i = lo; i <= hi; i++) {
      if (arr[i] > pivot) {
        temp[t] = arr[i];
        t++;
      }
    }
    for (let i = lo; i <= hi; i++) {
      arr[i] = temp[i];
    }
    if (ltEnd - 1 > lo) {
      stackLo[top] = lo;
      stackHi[top] = ltEnd - 1;
      top++;
    }
    if (hi > eqEnd) {
      stackLo[top] = eqEnd;
      stackHi[top] = hi;
      top++;
    }
  }
}