Binary MSD Radix Sort

Bitwise most-significant-bit-first partitioning radix sort for integer keys.

Best O(n) Avg O(nw) Worst O(nw) Space O(log n) Stable No In-place Yes Distribution

How it works

Bitwise most-significant-bit-first partitioning radix sort for integer keys.

Implementation

function binaryMSDRadixSort(arr, stats) {
  if (arr.length < 2) return;
  const metrics = stats.educational.metrics;
  const recordMetric = (name, delta = 1) => {
    metrics[name] = (metrics[name] || 0) + delta;
  };
  let min = arr[0];
  let max = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < min) min = arr[i];
    if (arr[i] > max) max = arr[i];
  }
  const offset = min < 0 ? -min : 0;
  const maxKey = max + offset;
  metrics.radixBase = 2;
  metrics.signedOffset = offset;
  let divisor = 1;
  while (Math.floor(maxKey / divisor) >= 2) divisor *= 2;
  function digitFor(value, currentDivisor) {
    recordMetric('bitInspections');
    return Math.floor((value + offset) / currentDivisor) % 2;
  }
  function sort(lo, hi, currentDivisor) {
    if (lo > hi) return;
    if (lo === hi || currentDivisor === 0) {
      for (let i = lo; i <= hi; i++) markSorted(i);
      return;
    }
    recordMetric('bitPasses');
    let i = lo;
    let j = hi;
    while (i <= j) {
      while (i <= j) {
        if (digitFor(arr[i], currentDivisor) !== 0) break;
        i++;
      }
      while (i <= j) {
        if (digitFor(arr[j], currentDivisor) === 0) break;
        j--;
      }
      if (i < j) {
        swap(i, j);
        const t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
        recordMetric('partitionSwaps');
        i++;
        j--;
      }
    }
    const nextDivisor = Math.floor(currentDivisor / 2);
    sort(lo, j, nextDivisor);
    sort(i, hi, nextDivisor);
  }
  sort(0, arr.length - 1, divisor);
}