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 runSize = Math.max(8, Math.floor(Math.sqrt(n))); const runs = []; for (let i = 0; i < n; i += runSize) { const run = arr.slice(i, Math.min(i + runSize, n)).sort((a, b) => a - b); runs.push(run); } const k = runs.length; const loser = new Array(k).fill(-1); const idx = new Array(k).fill(0); let winner = -1; function value(i) { if (i < 0 || idx[i] >= runs[i].length) return Infinity; return runs[i][idx[i]]; } function play(i) { let p = i + k >> 1; let w = i; while (p > 0) { const l = loser[p]; if (l === -1) { loser[p] = w; w = -1; break; } if (value(w) > value(l)) { loser[p] = w; w = l; } p >>= 1; } if (w !== -1) winner = w; } for (let i = 0; i < k; i++) play(i); for (let out = 0; out < n; out++) { arr[out] = value(winner); write(out, arr[out]); idx[winner]++; play(winner); } }
def sort(arr, n, stats): if (n < 2): return runSize = max(8, int(int(n ** 0.5))) runs = [] i = 0 while (i < n): run = arr[i:min((i + runSize), n)].sort(# UNSUPPORTED: ArrowFunctionExpression) runs.append(run) i += runSize k = len(runs) loser = [-1] * k idx = [0] * k winner = -1 def value(i): if ((i < 0) or (idx[i] >= len(runs[i]))): return Infinity return runs[i][idx[i]] def play(i): p = ((i + k) >> 1) w = i while (p > 0): l = loser[p] if (l == -1): loser[p] = w w = -1 break if (value(w) > value(l)): loser[p] = w w = l p >>= 1 if (w != -1): winner = w for i in range(k): play(i) for out in range(n): arr[out] = value(winner) idx[winner] += 1 play(winner)
#include <vector> #include <algorithm> #include <cstring> #include <cmath> void sort(std::vector<int>& arr, int n, int& comparisons, int& swaps) { int value(int i) { if(((i < 0) || (idx[i] >= n))) { return Infinity; } return runs[i][idx[i]]; } void play(int i) { int p = ((i + k) >> 1); int w = i; while((p > 0)) { int l = loser[p]; if((l == -1)) { loser[p] = w; w = -1; break; } if((value(w) > value(l))) { loser[p] = w; w = l; } p >>= 1; } if((w != -1)) { winner = w; } } if((n < 2)) { return; } int runSize = ((8) > ((int)std::floor((int)std::sqrt(n))) ? (8) : ((int)std::floor((int)std::sqrt(n)))); int runs = {}; for(int i=0; (i < n); i += runSize) { int run = arr_slice_sort(/* UNSUPPORTED: ArrowFunctionExpression */); runs[runs_len++] = run; } int k = n; std::vector<int> loser(k); for(int _i=0;_i<k;_i++) loser[_i]=-1; std::vector<int> idx(k); std::memset(idx, 0, sizeof(idx)); int winner = -1; for(int i=0; (i < k); i++) { play(i); } for(int out=0; (out < n); out++) { arr[out] = value(winner); idx[winner]++; play(winner); } }
public void Sort(int[] arr, int n, dynamic stats) { int value(int i) { if(((i < 0) || (idx[i] >= n))) { return Infinity; } return runs[i][idx[i]]; } void play(int i) { int p = ((i + k) >> 1); int w = i; while((p > 0)) { int l = loser[p]; if((l == -1)) { loser[p] = w; w = -1; break; } if((value(w) > value(l))) { loser[p] = w; w = l; } p >>= 1; } if((w != -1)) { winner = w; } } if((n < 2)) { return; } int runSize = ((8) > ((int)Math.Floor((int)Math.Sqrt(n))) ? (8) : ((int)Math.Floor((int)Math.Sqrt(n)))); int runs = {}; for(int i=0; (i < n); i += runSize) { int run = arr_slice_sort(/* UNSUPPORTED: ArrowFunctionExpression */); runs[runs_len++] = run; } int k = n; int[] loser = new int[k]; for(int _i=0;_i<k;_i++) loser[_i]=-1; int[] idx = new int[k]; Array.Clear(idx, 0, sizeof(idx)); int winner = -1; for(int i=0; (i < k); i++) { play(i); } for(int out=0; (out < n); out++) { arr[out] = value(winner); idx[winner]++; play(winner); } }
#include <stdio.h> #include <string.h> #include <math.h> void sort(int arr[], int n, int* comparisons, int* swaps) { int value(int i) { if(((i < 0) || (idx[i] >= n))) { return Infinity; } return runs[i][idx[i]]; } void play(int i) { int p = ((i + k) >> 1); int w = i; while((p > 0)) { int l = loser[p]; if((l == -1)) { loser[p] = w; w = -1; break; } if((value(w) > value(l))) { loser[p] = w; w = l; } p >>= 1; } if((w != -1)) { winner = w; } } if((n < 2)) { return; } int runSize = ((8) > ((int)floor((int)sqrt(n))) ? (8) : ((int)floor((int)sqrt(n)))); int runs = {}; for(int i=0; (i < n); i += runSize) { int run = arr_slice_sort(/* UNSUPPORTED: ArrowFunctionExpression */); runs[runs_len++] = run; } int k = n; int loser[k]; for(int _i=0;_i<k;_i++) loser[_i]=-1; int idx[k]; memset(idx, 0, sizeof(idx)); int winner = -1; for(int i=0; (i < k); i++) { play(i); } for(int out=0; (out < n); out++) { arr[out] = value(winner); idx[winner]++; play(winner); } }