Bitonic Sort

Builds and merges bitonic sequences through a fixed compare-exchange network. This arbitrary-length formulation splits on the greatest power of two below the range, so every comparator acts on real positions and the array is sorted in place. Highly parallelizable — the model behind GPU and hardware sorters.

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

How it works

Builds and merges bitonic sequences through a fixed compare-exchange network. This arbitrary-length formulation splits on the greatest power of two below the range, so every comparator acts on real positions and the array is sorted in place. Highly parallelizable — the model behind GPU and hardware sorters.

Implementation

function bitonicSort(arr, stats) {
  const n = arr.length;
  if (n < 2) {
    if (n === 1) markSorted(0);
    return;
  }
  const metrics = stats.educational.metrics;
  const recordMetric = (name, delta = 1) => {
    metrics[name] = (metrics[name] || 0) + delta;
  };
  function greatestPowerOfTwoBelow(value) {
    let power = 1;
    while (power < value) power <<= 1;
    return power >> 1;
  }
  function compareExchange(i, j, ascending) {
    compare(i, j);
    recordMetric('compareExchanges');
    if (ascending === arr[i] > arr[j]) {
      swap(i, j);
      const t = arr[i];
      arr[i] = arr[j];
      arr[j] = t;
      recordMetric('exchangeSwaps');
    }
  }
  function bitonicMerge(lo, count, ascending) {
    if (count <= 1) return;
    recordMetric('mergePasses');
    const m = greatestPowerOfTwoBelow(count);
    for (let i = lo; i < lo + count - m; i++) compareExchange(i, i + m, ascending);
    bitonicMerge(lo, m, ascending);
    bitonicMerge(lo + m, count - m, ascending);
  }
  function bitonicSort(lo, count, ascending) {
    if (count <= 1) return;
    recordMetric('sequenceBuilds');
    const m = count >> 1;
    bitonicSort(lo, m, !ascending);
    bitonicSort(lo + m, count - m, ascending);
    bitonicMerge(lo, count, ascending);
    checkpoint(Math.min(lo + count, n), n);
  }
  bitonicSort(0, n, true);
  for (let i = 0; i < n; i++) markSorted(i);
}