Sample Sort

Generalizes quicksort to many pivots: it draws a set of splitter samples, distributes each range into buckets between consecutive splitters, writes the buckets straight back, and recurses. Each level visibly regroups the bars into ordered buckets.

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

How it works

Generalizes quicksort to many pivots: it draws a set of splitter samples, distributes each range into buckets between consecutive splitters, writes the buckets straight back, and recurses. Each level visibly regroups the bars into ordered buckets.

Implementation

function sampleSort(arr, stats) {
  function sortRange(input) {
    const n = input.length;
    if (n <= 32) {
      for (let i = 1; i < n; i++) {
        const key = input[i];
        let j = i - 1;
        while (j >= 0) {
          if (input[j] <= key) break;
          input[j + 1] = input[j];
          j--;
        }
        input[j + 1] = key;
      }
      return input;
    }
    const sampleCount = Math.max(3, Math.min(15, Math.floor(Math.sqrt(n))));
    const step = Math.max(1, Math.floor(n / sampleCount));
    const samples = [];
    for (let i = 0; i < n && samples.length < sampleCount; i += step) samples.push(input[i]);
    samples.sort((a, b) => a - b);
    const buckets = new Array(samples.length + 1).fill(null).map(() => []);
    for (const value of input) {
      let bi = 0;
      while (bi < samples.length) {
        if (value < samples[bi]) break;
        bi++;
      }
      buckets[bi].push(value);
    }
    const out = [];
    for (const bucket of buckets) {
      const sorted = sortRange(bucket);
      for (const v of sorted) out.push(v);
    }
    return out;
  }
  const out = sortRange(arr.slice());
  for (let i = 0; i < out.length; i++) {
    arr[i] = out[i];
    write(i, arr[i]);
  }
}