Bucket Sort

Distributes elements into buckets, sorts each bucket individually (usually with insertion sort), then concatenates.

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

How it works

Distributes elements into buckets, sorts each bucket individually (usually with insertion sort), then concatenates.

Implementation

function bucketSort(arr, stats) {
  const n = arr.length;
  if (n < 2) {
    if (n === 1) markSorted(0);
    return;
  }
  let min = arr[0];
  let max = arr[0];
  for (let i = 1; i < n; i++) {
    if (arr[i] < min) min = arr[i];
    if (arr[i] > max) max = arr[i];
  }
  const metrics = stats.educational.metrics;
  const recordMetric = (name, delta = 1) => {
    metrics[name] = (metrics[name] || 0) + delta;
  };
  if (min === max) {
    for (let i = 0; i < n; i++) markSorted(i);
    checkpoint(n, n);
    return;
  }
  const bucketCount = n;
  const range = max - min;
  const buckets = Array.from({
    length: bucketCount
  }, () => []);
  metrics.bucketCount = bucketCount;
  for (let i = 0; i < n; i++) {
    const normalized = (arr[i] - min) / range;
    const bucketIndex = Math.min(bucketCount - 1, Math.floor(normalized * (bucketCount - 1)));
    buckets[bucketIndex].push(arr[i]);
    recordMetric('bucketAssignments');
    recordMetric('distributionReads');
  }
  function sortBucket(bucket) {
    recordMetric('bucketSortCalls');
    for (let i = 1; i < bucket.length; i++) {
      const value = bucket[i];
      let j = i;
      while (j > 0) {
        if (bucket[j - 1] <= value) break;
        bucket[j] = bucket[j - 1];
        j--;
        recordMetric('bucketShifts');
      }
      bucket[j] = value;
    }
  }
  let write = 0;
  for (let bucketIndex = 0; bucketIndex < bucketCount; bucketIndex++) {
    const bucket = buckets[bucketIndex];
    if (bucket.length > 1) sortBucket(bucket);
    for (let i = 0; i < bucket.length; i++) {
      arr[write] = bucket[i];
      recordMetric('outputWrites');
      write(write, arr[write]);
      markSorted(write);
      write++;
    }
    checkpoint(write, n);
  }
}