American Flag Sort

In-place MSD radix distribution using cycle-leader style bucket placement.

Best O(n) Avg O(n) Worst O(nk) Space O(k) Stable No In-place Yes Distribution

How it works

In-place MSD radix distribution using cycle-leader style bucket placement.

Implementation

function americanFlagSort(arr, stats) {
  if (arr.length < 2) return;
  let max = 0;
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] > max) max = arr[i];
  }
  const RADIX = 256;
  let exp = 1;
  while (Math.floor(max / exp) >= RADIX) exp *= RADIX;
  function sortRange(lo, hi, e) {
    if (hi - lo <= 1 || e === 0) return;
    const count = new Array(RADIX).fill(0);
    for (let i = lo; i < hi; i++) {
      const d = Math.floor(arr[i] / e) % RADIX;
      count[d]++;
    }
    const start = new Array(RADIX).fill(0);
    const next = new Array(RADIX).fill(0);
    let sum = lo;
    for (let i = 0; i < RADIX; i++) {
      start[i] = sum;
      next[i] = sum;
      sum += count[i];
    }
    for (let b = 0; b < RADIX; b++) {
      let i = next[b];
      const end = start[b] + count[b];
      while (i < end) {
        const d = Math.floor(arr[i] / e) % RADIX;
        if (d === b) {
          i++;
        } else {
          const to = next[d]++;
          swap(i, to);
          const t = arr[i];
          arr[i] = arr[to];
          arr[to] = t;
        }
      }
    }
    if (e > 1) {
      for (let b = 0; b < RADIX; b++) {
        if (count[b] > 1) sortRange(start[b], start[b] + count[b], Math.floor(e / RADIX));
      }
    }
  }
  sortRange(0, arr.length, exp);
}