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 source = [...arr]; const runSize = Math.min(n, Math.max(8, Math.floor(Math.sqrt(n)))); const runs = []; const sortRun = run => { for (let i = 1; i < run.length; i++) { const value = run[i]; let j = i - 1; while (j >= 0) { if (run[j] <= value) break; run[j + 1] = run[j]; j--; } run[j + 1] = value; } return run; }; for (let i = 0; i < n; i += runSize) { const run = source.slice(i, Math.min(i + runSize, n)); runs.push(sortRun(run)); } const k = runs.length; const idx = new Array(k).fill(0); let previewWrite = 0; for (let runIndex = 0; runIndex < runs.length; runIndex++) { const run = runs[runIndex]; for (let valueIndex = 0; valueIndex < run.length; valueIndex++) { const value = run[valueIndex]; arr[previewWrite] = value; write(previewWrite, value); previewWrite++; } } const value = i => { if (i < 0 || i >= k || idx[i] >= runs[i].length) return Infinity; return runs[i][idx[i]]; }; let leafCount = 1; while (leafCount < k) leafCount <<= 1; const selectWinner = (node, loserTree) => { if (node >= leafCount) { const player = node - leafCount; return player < k ? player : -1; } const leftWinner = selectWinner(node * 2, loserTree); const rightWinner = selectWinner(node * 2 + 1, loserTree); const leftValue = value(leftWinner); const rightValue = value(rightWinner); if (leftWinner >= 0 && rightWinner >= 0) {} if (leftValue <= rightValue) { loserTree[node] = rightWinner; return leftWinner; } loserTree[node] = leftWinner; return rightWinner; }; for (let out = 0; out < n; out++) { const loserTree = new Array(leafCount * 2).fill(-1); const winner = selectWinner(1, loserTree); arr[out] = value(winner); write(out, arr[out]); markSorted(out); idx[winner]++; } }
def loserTreeSort(arr, stats): def sortRun(run): for i in range(1, len(run)): value = run[i] j = (i - 1) while (j >= 0): if (run[j] <= value): break run[(j + 1)] = run[j] j -= 1 run[(j + 1)] = value return run def value(i): if (((i < 0) or (i >= k)) or (idx[i] >= len(runs[i]))): return float('inf') return runs[i][idx[i]] def selectWinner(node, loserTree): if (node >= leafCount): player = (node - leafCount) return (player if (player < k) else -1) leftWinner = selectWinner((node * 2), loserTree) rightWinner = selectWinner(((node * 2) + 1), loserTree) leftValue = value(leftWinner) rightValue = value(rightWinner) if ((leftWinner >= 0) and (rightWinner >= 0)): pass if (leftValue <= rightValue): loserTree[node] = rightWinner return leftWinner loserTree[node] = leftWinner return rightWinner if (n < 2): return source = [*arr] runSize = (n if n <= (8 if 8 >= int(int(n ** 0.5)) else int(int(n ** 0.5))) else (8 if 8 >= int(int(n ** 0.5)) else int(int(n ** 0.5)))) runs = [] for i in range(0, n, runSize): run = source[i:((i + runSize) if (i + runSize) <= n else n)] runs.append(sortRun(run)) k = len(runs) idx = [0] * k previewWrite = 0 for runIndex in range(len(runs)): run = runs[runIndex] for valueIndex in range(len(run)): value = run[valueIndex] arr[previewWrite] = value write(previewWrite, value) previewWrite += 1 leafCount = 1 while (leafCount < k): leafCount <<= 1 for out in range(n): loserTree = [-1] * (leafCount * 2) winner = selectWinner(1, loserTree) arr[out] = value(winner) write(out, arr[out]) markSorted(out) idx[winner] += 1
#include <vector> #include <algorithm> #include <cmath> int sortRun(int run); int value(int i); int selectWinner(int node, int loserTree); int sortRun(int run) { for(int i=1; i<n; i++) { int value = run[i]; int j = (i - 1); while((j >= 0)) { if((run[j] <= value)) { break; } run[(j + 1)] = run[j]; j--; } run[(j + 1)] = value; } return run; } int value(int i) { if((((i < 0) || (i >= k)) || (idx[i] >= n))) { return 2147483647; } return runs[i][idx[i]]; } int selectWinner(int node, int loserTree) { if((node >= leafCount)) { int player = (node - leafCount); return (((player < k)) ? (player) : (-1)); } int leftWinner = selectWinner((node * 2), loserTree); int rightWinner = selectWinner(((node * 2) + 1), loserTree); int leftValue = value(leftWinner); int rightValue = value(rightWinner); if(((leftWinner >= 0) && (rightWinner >= 0))) { } if((leftValue <= rightValue)) { loserTree[node] = rightWinner; return leftWinner; } loserTree[node] = leftWinner; return rightWinner; } void sort(std::vector<int>& arr, int n, int& comparisons, int& swaps) { if((n < 2)) { return; } std::vector<int> source = {arr}; int runSize = ((n) < (((8) > ((int)std::floor((int)std::sqrt(n))) ? (8) : ((int)std::floor((int)std::sqrt(n))))) ? (n) : (((8) > ((int)std::floor((int)std::sqrt(n))) ? (8) : ((int)std::floor((int)std::sqrt(n)))))); std::vector<int> runs; for(int i=0; i<n; i+=runSize) { int _run_len = (((i + runSize)) < (n) ? ((i + runSize)) : (n)) - (i); std::vector<int> run(source.begin() + (i), source.begin() + ((((i + runSize)) < (n) ? ((i + runSize)) : (n)))); runs.push_back(sortRun(run)); } int k = (int)runs.size(); std::vector<int> idx(k, 0); int previewWrite = 0; for(int runIndex=0; runIndex<(int)runs.size(); runIndex++) { int run = runs[runIndex]; for(int valueIndex=0; valueIndex<_run_len; valueIndex++) { int value = run[valueIndex]; arr[previewWrite] = value; write(previewWrite, value); previewWrite++; } } int leafCount = 1; while((leafCount < k)) { leafCount <<= 1; } for(int out=0; out<n; out++) { std::vector<int> loserTree((leafCount * 2), -1); int winner = selectWinner(1, loserTree); arr[out] = value(winner); write(out, arr[out]); markSorted(out); idx[winner]++; } }
int sortRun(int run) { for(int i=1; i<n; i++) { int value = run[i]; int j = (i - 1); while((j >= 0)) { if((run[j] <= value)) { break; } run[(j + 1)] = run[j]; j--; } run[(j + 1)] = value; } return run; } int value(int i) { if((((i < 0) || (i >= k)) || (idx[i] >= n))) { return int.MaxValue; } return runs[i][idx[i]]; } int selectWinner(int node, int loserTree) { if((node >= leafCount)) { int player = (node - leafCount); return (((player < k)) ? (player) : (-1)); } int leftWinner = selectWinner((node * 2), loserTree); int rightWinner = selectWinner(((node * 2) + 1), loserTree); int leftValue = value(leftWinner); int rightValue = value(rightWinner); if(((leftWinner >= 0) && (rightWinner >= 0))) { } if((leftValue <= rightValue)) { loserTree[node] = rightWinner; return leftWinner; } loserTree[node] = leftWinner; return rightWinner; } public void Sort(int[] arr, int n, dynamic stats) { if((n < 2)) { return; } var source = new List<int> { arr }; int runSize = Math.Min(n, Math.Max(8, (int)Math.Floor((double)(int)Math.Sqrt(n)))); var runs = new List<int>(); for(int i=0; i<n; i+=runSize) { int _run_len = Math.Min((i + runSize), n) - (i); int[] run = new int[_run_len]; Array.Copy(source, i, run, 0, _run_len); runs.Add(sortRun(run)); } int k = runs.Count; int[] idx = new int[k]; int previewWrite = 0; for(int runIndex=0; runIndex<runs.Count; runIndex++) { int run = runs[runIndex]; for(int valueIndex=0; valueIndex<_run_len; valueIndex++) { int value = run[valueIndex]; arr[previewWrite] = value; write(previewWrite, value); previewWrite++; } } int leafCount = 1; while((leafCount < k)) { leafCount <<= 1; } for(int out=0; out<n; out++) { int[] loserTree = new int[(leafCount * 2)]; for(int _i=0;_i<(leafCount * 2);_i++) loserTree[_i]=-1; int winner = selectWinner(1, loserTree); arr[out] = value(winner); write(out, arr[out]); markSorted(out); idx[winner]++; } }
#include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> int sortRun(int run); int value(int i); int selectWinner(int node, int loserTree); int sortRun(int run) { for(int i=1; i<n; i++) { int value = run[i]; int j = (i - 1); while((j >= 0)) { if((run[j] <= value)) { break; } run[(j + 1)] = run[j]; j--; } run[(j + 1)] = value; } return run; } int value(int i) { if((((i < 0) || (i >= k)) || (idx[i] >= n))) { return 2147483647; } return runs[i][idx[i]]; } int selectWinner(int node, int loserTree) { if((node >= leafCount)) { int player = (node - leafCount); return (((player < k)) ? (player) : (-1)); } int leftWinner = selectWinner((node * 2), loserTree); int rightWinner = selectWinner(((node * 2) + 1), loserTree); int leftValue = value(leftWinner); int rightValue = value(rightWinner); if(((leftWinner >= 0) && (rightWinner >= 0))) { } if((leftValue <= rightValue)) { loserTree[node] = rightWinner; return leftWinner; } loserTree[node] = leftWinner; return rightWinner; } void sort(int arr[], int n, int* comparisons, int* swaps) { if((n < 2)) { return; } int* source = (int*)malloc(n * sizeof(int)); int source_len = 1; source[0] = arr; int runSize = ((n) < (((8) > ((int)floor((int)sqrt(n))) ? (8) : ((int)floor((int)sqrt(n))))) ? (n) : (((8) > ((int)floor((int)sqrt(n))) ? (8) : ((int)floor((int)sqrt(n)))))); int* runs = (int*)malloc(n * sizeof(int)); int runs_len = 0; for(int i=0; i<n; i+=runSize) { int _run_len = (((i + runSize)) < (n) ? ((i + runSize)) : (n)) - (i); int* run = (int*)malloc((_run_len) * sizeof(int)); for(int _ci=0;_ci<_run_len;_ci++) run[_ci]=source[(i)+_ci]; runs[runs_len++] = sortRun(run); } int k = runs_len; int* idx = (int*)malloc((k) * sizeof(int)); memset(idx, 0, (k) * sizeof(int)); int previewWrite = 0; for(int runIndex=0; runIndex<runs_len; runIndex++) { int run = runs[runIndex]; for(int valueIndex=0; valueIndex<_run_len; valueIndex++) { int value = run[valueIndex]; arr[previewWrite] = value; write(previewWrite, value); previewWrite++; } } int leafCount = 1; while((leafCount < k)) { leafCount <<= 1; } for(int out=0; out<n; out++) { int* loserTree = (int*)malloc(((leafCount * 2)) * sizeof(int)); for(int _i=0;_i<(leafCount * 2);_i++) loserTree[_i]=-1; int winner = selectWinner(1, loserTree); arr[out] = value(winner); write(out, arr[out]); markSorted(out); idx[winner]++; } }