Multikey Quicksort

3-way quicksort over key symbols/characters, ideal for string-like keys.

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

How it works

3-way quicksort over key symbols/characters, ideal for string-like keys.

Implementation

function multikeyQuickSort(arr, stats) {
  const n = arr.length;
  if (n < 2) return;
  let max = arr[0];
  for (let i = 1; i < n; i++) {
    if (arr[i] > max) max = arr[i];
  }
  let maxLen = 1;
  let p = 10;
  while (p <= max) {
    maxLen++;
    p = p * 10;
  }
  const pow = new Array(maxLen).fill(1);
  let e = 1;
  for (let d = maxLen - 1; d >= 0; d--) {
    pow[d] = e;
    e = e * 10;
  }
  const cap = 3 * n + 3 * maxLen + 16;
  const stackLo = new Array(cap).fill(0);
  const stackHi = new Array(cap).fill(0);
  const stackD = new Array(cap).fill(0);
  let top = 0;
  stackLo[top] = 0;
  stackHi[top] = n - 1;
  stackD[top] = 0;
  top++;
  while (top > 0) {
    top--;
    const lo = stackLo[top];
    const hi = stackHi[top];
    const d = stackD[top];
    if (lo >= hi || d >= maxLen) continue;
    const pivot = Math.floor(arr[lo] / pow[d]) % 10;
    let lt = lo;
    let gt = hi;
    let i = lo;
    while (i <= gt) {
      const digit = Math.floor(arr[i] / pow[d]) % 10;
      if (digit < pivot) {
        const t = arr[lt];
        arr[lt] = arr[i];
        arr[i] = t;
        lt++;
        i++;
      } else if (digit > pivot) {
        const t = arr[i];
        arr[i] = arr[gt];
        arr[gt] = t;
        gt--;
      } else {
        i++;
      }
    }
    if (lt - 1 > lo) {
      stackLo[top] = lo;
      stackHi[top] = lt - 1;
      stackD[top] = d;
      top++;
    }
    if (gt > lt && d + 1 < maxLen) {
      stackLo[top] = lt;
      stackHi[top] = gt;
      stackD[top] = d + 1;
      top++;
    }
    if (hi > gt + 1) {
      stackLo[top] = gt + 1;
      stackHi[top] = hi;
      stackD[top] = d;
      top++;
    }
  }
}