Weak-Heap Sort

Minimizes branches.

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

How it works

Minimizes branches.

Implementation

function weakHeapSort(arr, stats) {
  const n = arr.length;
  if (n < 2) return;
  const reverse = new Uint8Array(n);
  const metrics = stats.educational.metrics;
  let finalized = 0;
  const recordMetric = (name, delta = 1) => {
    metrics[name] = (metrics[name] || 0) + delta;
  };
  metrics.reverseBits = n;
  function swap(i, j) {
    if (i === j) return;
    swap(i, j);
    const value = arr[i];
    arr[i] = arr[j];
    arr[j] = value;
    recordMetric('pairSwaps');
  }
  function markIndex(index) {
    markSorted(index);
    finalized++;
    if (finalized > n) finalized = n;
    checkpoint(finalized, n);
  }
  function distinguishedAncestor(index) {
    let ancestor = index;
    while ((ancestor & 1) === reverse[ancestor >> 1]) {
      ancestor >>= 1;
      recordMetric('ancestorWalkSteps');
    }
    return ancestor >> 1;
  }
  function join(root, child) {
    compare(root, child);
    recordMetric('joinCalls');
    if (arr[root] < arr[child]) {
      reverse[child] ^= 1;
      recordMetric('reverseBitFlips');
      swap(root, child);
    }
  }
  for (let child = n - 1; child > 0; child--) {
    join(distinguishedAncestor(child), child);
    recordMetric('heapBuildPasses');
  }
  for (let end = n - 1; end > 1; end--) {
    swap(0, end);
    markIndex(end);
    recordMetric('extractionPasses');
    let node = 1;
    while ((node << 1) + reverse[node] < end) {
      node = (node << 1) + reverse[node];
      recordMetric('leafWalkSteps');
    }
    while (node > 0) {
      join(0, node);
      node >>= 1;
      if (node > 0) recordMetric('restoreClimbs');
    }
  }
  compare(0, 1);
  if (arr[0] > arr[1]) swap(0, 1);
  markIndex(1);
  markIndex(0);
}