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]); } }
def sort(arr, n, stats): if (n < 2): return heapSize = max(4, int(int(n ** 0.5))) heap = arr[0:heapSize] inputIdx = heapSize runs = [] currentRun = [] def siftDown(h, i): while True: smallest = i l = ((i * 2) + 1) r = (l + 1) if (l < len(h)): if (h[l] < h[smallest]): smallest = l if (r < len(h)): if (h[r] < h[smallest]): smallest = r if (smallest == i): break t = h[i] h[i] = h[smallest] h[smallest] = t i = smallest def heapify(h): for i in range(((len(h) >> 1) - 1), 0 - 1, -1): siftDown(h, i) heapify(heap) frozen = [] lastOut = -Infinity while len(heap): minVal = heap[0] currentRun.append(minVal) lastOut = minVal if (inputIdx < n): next = arr[inputIdx] if (next >= lastOut): heap[0] = next else: heap[0] = heap[(len(heap) - 1)] heap.pop() frozen.append(next) else: heap[0] = heap[(len(heap) - 1)] heap.pop() if len(heap): siftDown(heap, 0) if (not len(heap) and len(frozen)): runs.append(currentRun) currentRun = [] heap = frozen frozen = [] heapify(heap) lastOut = -Infinity if len(currentRun): runs.append(currentRun) ptr = [0] * len(runs) for k in range(n): ri = -1 best = 0 for r in range(len(runs)): if (ptr[r] >= len(runs[r])): continue v = runs[r][ptr[r]] if ((ri == -1) or (v < best)): if (ri != -1): ri = r best = v arr[k] = best ptr[ri] += 1
#include <vector> #include <algorithm> #include <cstring> #include <cmath> void sort(std::vector<int>& arr, int n, int& comparisons, int& swaps) { void siftDown(int h, int i) { while(1) { int smallest = i; int l = ((i * 2) + 1); int r = (l + 1); if((l < n)) { if((h[l] < h[smallest])) { smallest = l; } } if((r < n)) { if((h[r] < h[smallest])) { smallest = r; } } if((smallest == i)) { break; } int t = h[i]; h[i] = h[smallest]; h[smallest] = t; i = smallest; } } void heapify(int h) { for(int i=((n >> 1) - 1); (i >= 0); i--) { siftDown(h, i); } } if((n < 2)) { return; } int heapSize = ((4) > ((int)std::floor((int)std::sqrt(n))) ? (4) : ((int)std::floor((int)std::sqrt(n)))); int _heap_len = heapSize - (0); std::vector<int> heap(_heap_len); for(int _ci=0;_ci<_heap_len;_ci++) heap[_ci]=arr[(0)+_ci]; int inputIdx = heapSize; int runs = {}; int currentRun = {}; heapify(heap); int frozen = {}; int lastOut = -Infinity; while(_heap_len) { int minVal = heap[0]; currentRun[currentRun_len++] = minVal; lastOut = minVal; if((inputIdx < n)) { int next = arr[inputIdx++]; if((next >= lastOut)) { heap[0] = next; } else { heap[0] = heap[(_heap_len - 1)]; heap_pop(); frozen[frozen_len++] = next; } } else { heap[0] = heap[(_heap_len - 1)]; heap_pop(); } if(_heap_len) { siftDown(heap, 0); } if((!_heap_len && n)) { runs[runs_len++] = currentRun; currentRun = {}; heap = frozen; frozen = {}; heapify(heap); lastOut = -Infinity; } } if(n) { runs[runs_len++] = currentRun; } std::vector<int> ptr(n); std::memset(ptr, 0, sizeof(ptr)); for(int k=0; (k < n); k++) { int ri = -1; int best = 0; for(int r=0; (r < n); r++) { if((ptr[r] >= n)) { continue; } int v = runs[r][ptr[r]]; if(((ri == -1) || (v < best))) { if((ri != -1)) { } ri = r; best = v; } } arr[k] = best; ptr[ri]++; } }
public void Sort(int[] arr, int n, dynamic stats) { void siftDown(int h, int i) { while(1) { int smallest = i; int l = ((i * 2) + 1); int r = (l + 1); if((l < n)) { if((h[l] < h[smallest])) { smallest = l; } } if((r < n)) { if((h[r] < h[smallest])) { smallest = r; } } if((smallest == i)) { break; } int t = h[i]; h[i] = h[smallest]; h[smallest] = t; i = smallest; } } void heapify(int h) { for(int i=((n >> 1) - 1); (i >= 0); i--) { siftDown(h, i); } } if((n < 2)) { return; } int heapSize = ((4) > ((int)Math.Floor((int)Math.Sqrt(n))) ? (4) : ((int)Math.Floor((int)Math.Sqrt(n)))); int _heap_len = heapSize - (0); int[] heap = new int[_heap_len]; for(int _ci=0;_ci<_heap_len;_ci++) heap[_ci]=arr[(0)+_ci]; int inputIdx = heapSize; int runs = {}; int currentRun = {}; heapify(heap); int frozen = {}; int lastOut = -Infinity; while(_heap_len) { int minVal = heap[0]; currentRun[currentRun_len++] = minVal; lastOut = minVal; if((inputIdx < n)) { int next = arr[inputIdx++]; if((next >= lastOut)) { heap[0] = next; } else { heap[0] = heap[(_heap_len - 1)]; heap_pop(); frozen[frozen_len++] = next; } } else { heap[0] = heap[(_heap_len - 1)]; heap_pop(); } if(_heap_len) { siftDown(heap, 0); } if((!_heap_len && n)) { runs[runs_len++] = currentRun; currentRun = {}; heap = frozen; frozen = {}; heapify(heap); lastOut = -Infinity; } } if(n) { runs[runs_len++] = currentRun; } int[] ptr = new int[n]; Array.Clear(ptr, 0, sizeof(ptr)); for(int k=0; (k < n); k++) { int ri = -1; int best = 0; for(int r=0; (r < n); r++) { if((ptr[r] >= n)) { continue; } int v = runs[r][ptr[r]]; if(((ri == -1) || (v < best))) { if((ri != -1)) { } ri = r; best = v; } } arr[k] = best; ptr[ri]++; } }
#include <stdio.h> #include <string.h> #include <math.h> void sort(int arr[], int n, int* comparisons, int* swaps) { void siftDown(int h, int i) { while(1) { int smallest = i; int l = ((i * 2) + 1); int r = (l + 1); if((l < n)) { if((h[l] < h[smallest])) { smallest = l; } } if((r < n)) { if((h[r] < h[smallest])) { smallest = r; } } if((smallest == i)) { break; } int t = h[i]; h[i] = h[smallest]; h[smallest] = t; i = smallest; } } void heapify(int h) { for(int i=((n >> 1) - 1); (i >= 0); i--) { siftDown(h, i); } } if((n < 2)) { return; } int heapSize = ((4) > ((int)floor((int)sqrt(n))) ? (4) : ((int)floor((int)sqrt(n)))); int _heap_len = heapSize - (0); int heap[_heap_len]; for(int _ci=0;_ci<_heap_len;_ci++) heap[_ci]=arr[(0)+_ci]; int inputIdx = heapSize; int runs = {}; int currentRun = {}; heapify(heap); int frozen = {}; int lastOut = -Infinity; while(_heap_len) { int minVal = heap[0]; currentRun[currentRun_len++] = minVal; lastOut = minVal; if((inputIdx < n)) { int next = arr[inputIdx++]; if((next >= lastOut)) { heap[0] = next; } else { heap[0] = heap[(_heap_len - 1)]; heap_pop(); frozen[frozen_len++] = next; } } else { heap[0] = heap[(_heap_len - 1)]; heap_pop(); } if(_heap_len) { siftDown(heap, 0); } if((!_heap_len && n)) { runs[runs_len++] = currentRun; currentRun = {}; heap = frozen; frozen = {}; heapify(heap); lastOut = -Infinity; } } if(n) { runs[runs_len++] = currentRun; } int ptr[n]; memset(ptr, 0, sizeof(ptr)); for(int k=0; (k < n); k++) { int ri = -1; int best = 0; for(int r=0; (r < n); r++) { if((ptr[r] >= n)) { continue; } int v = runs[r][ptr[r]]; if(((ri == -1) || (v < best))) { if((ri != -1)) { } ri = r; best = v; } } arr[k] = best; ptr[ri]++; } }