Loser Tree Sort

Tournament-tree k-way merge method optimized for repeatedly selecting next minimum.

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

How it works

Tournament-tree k-way merge method optimized for repeatedly selecting next minimum.

Implementation

function loserTreeSort(arr, stats) {
  const n = arr.length;
  if (n < 2) return;
  const runLen = Math.max(2, Math.floor(Math.sqrt(n)));
  for (let lo = 0; lo < n; lo += runLen) {
    const hi = Math.min(lo + runLen, n);
    for (let i = lo + 1; i < hi; i++) {
      const key = arr[i];
      let j = i - 1;
      while (j >= lo && arr[j] > key) {
        arr[j + 1] = arr[j];
        j--;
      }
      arr[j + 1] = key;
    }
  }
  let runs = 0;
  for (let lo = 0; lo < n; lo += runLen) {
    runs++;
  }
  const head = new Array(runs).fill(0);
  const end = new Array(runs).fill(0);
  let r = 0;
  for (let lo = 0; lo < n; lo += runLen) {
    head[r] = lo;
    end[r] = Math.min(lo + runLen, n);
    r++;
  }
  const heap = new Array(runs).fill(0);
  let hs = 0;
  for (let t = 0; t < runs; t++) {
    heap[hs] = t;
    let c = hs;
    hs++;
    while (c > 0) {
      const par = (c - 1) >> 1;
      if (arr[head[heap[par]]] <= arr[head[heap[c]]]) break;
      const tmp = heap[par];
      heap[par] = heap[c];
      heap[c] = tmp;
      c = par;
    }
  }
  const output = new Array(n).fill(0);
  for (let o = 0; o < n; o++) {
    const run = heap[0];
    output[o] = arr[head[run]];
    head[run]++;
    if (head[run] >= end[run]) {
      hs--;
      heap[0] = heap[hs];
    }
    let c = 0;
    while (true) {
      const l = 2 * c + 1;
      const rr = 2 * c + 2;
      let small = c;
      if (l < hs && arr[head[heap[l]]] < arr[head[heap[small]]]) small = l;
      if (rr < hs && arr[head[heap[rr]]] < arr[head[heap[small]]]) small = rr;
      if (small === c) break;
      const tmp = heap[c];
      heap[c] = heap[small];
      heap[small] = tmp;
      c = small;
    }
  }
  for (let i = 0; i < n; i++) {
    arr[i] = output[i];
  }
}