Replacement Selection Sort

Heap-driven run generation technique commonly paired with external merge pipelines.

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

How it works

Heap-driven run generation technique commonly paired with external merge pipelines.

Implementation

function replacementSelectionSort(arr, stats) {
  const n = arr.length;
  if (n < 2) return;
  const heapSize = Math.max(4, Math.floor(Math.sqrt(n)));
  let heap = arr.slice(0, heapSize);
  let inputIdx = heapSize;
  const runs = [];
  let currentRun = [];
  function siftDown(h, i) {
    while (true) {
      let smallest = i;
      const l = i * 2 + 1;
      const r = l + 1;
      if (l < h.length) {
        if (h[l] < h[smallest]) smallest = l;
      }
      if (r < h.length) {
        if (h[r] < h[smallest]) smallest = r;
      }
      if (smallest === i) break;
      const t = h[i];
      h[i] = h[smallest];
      h[smallest] = t;
      i = smallest;
    }
  }
  function heapify(h) {
    for (let i = (h.length >> 1) - 1; i >= 0; i--) siftDown(h, i);
  }
  heapify(heap);
  let frozen = [];
  let lastOut = -Infinity;
  while (heap.length) {
    const minVal = heap[0];
    currentRun.push(minVal);
    lastOut = minVal;
    if (inputIdx < n) {
      const next = arr[inputIdx++];
      if (next >= lastOut) heap[0] = next; else {
        heap[0] = heap[heap.length - 1];
        heap.pop();
        frozen.push(next);
      }
    } else {
      heap[0] = heap[heap.length - 1];
      heap.pop();
    }
    if (heap.length) siftDown(heap, 0);
    if (!heap.length && frozen.length) {
      runs.push(currentRun);
      currentRun = [];
      heap = frozen;
      frozen = [];
      heapify(heap);
      lastOut = -Infinity;
    }
  }
  if (currentRun.length) runs.push(currentRun);
  const ptr = new Array(runs.length).fill(0);
  for (let k = 0; k < n; k++) {
    let ri = -1;
    let best = 0;
    for (let r = 0; r < runs.length; r++) {
      if (ptr[r] >= runs[r].length) continue;
      const v = runs[r][ptr[r]];
      if (ri === -1 || v < best) {
        if (ri !== -1) stats.comparisons++;
        ri = r;
        best = v;
      }
    }
    arr[k] = best;
    ptr[ri]++;
    write(k, arr[k]);
  }
}