WikiSort

Stable in-place merge sort in the WikiSort family: builds short runs with insertion sort, then repeatedly merges adjacent runs in place using rotations and shifts rather than an auxiliary buffer.

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

How it works

Stable in-place merge sort in the WikiSort family: builds short runs with insertion sort, then repeatedly merges adjacent runs in place using rotations and shifts rather than an auxiliary buffer.

Implementation

function wikiSort(arr, stats) {
  const n = arr.length;
  const run = 16;
  function insertion(lo, hi) {
    for (let i = lo + 1; i <= hi; i++) {
      const key = arr[i];
      let j = i - 1;
      while (j >= lo) {
        compare(j, j + 1);
        if (arr[j] <= key) break;
        arr[j + 1] = arr[j];
        swap(j + 1, j);
        j--;
      }
      arr[j + 1] = key;
    }
  }
  function mergeInPlace(lo, mid, hi) {
    if (lo > mid || mid >= hi) return;
    compare(mid, mid + 1);
    if (arr[mid] <= arr[mid + 1]) return;
    let i = lo;
    let j = mid + 1;
    while (i < j && j <= hi) {
      compare(i, j);
      if (arr[i] <= arr[j]) {
        i++;
      } else {
        const val = arr[j];
        let k = j;
        while (k > i) {
          arr[k] = arr[k - 1];
          swap(k, k - 1);
          k--;
        }
        arr[i] = val;
        i++;
        j++;
      }
    }
  }
  for (let i = 0; i < n; i += run) insertion(i, Math.min(i + run - 1, n - 1));
  for (let width = run; width < n; width <<= 1) {
    for (let i = 0; i < n; i += width << 1) {
      const lo = i;
      const mid = Math.min(i + width - 1, n - 1);
      const hi = Math.min(i + (width << 1) - 1, n - 1);
      if (mid < hi) mergeInPlace(lo, mid, hi);
    }
    checkpoint(Math.min(width << 1, n), n);
  }
  for (let i = 0; i < n; i++) markSorted(i);
}