UNPKG

@zzopark/zzosort

Version:
112 lines (96 loc) 2.79 kB
const zzosort = (function() { const iParent = i => Math.floor((i - 1) / 2); const iLeftChild = i => 2 * i + 1; const iRightChild = i => 2 * i + 2; function swap(items, a, b) { let temp = items[a]; items[a] = items[b]; items[b] = temp; } function pivot(items, lo, hi, cmpf) { const mid = Math.floor((lo + hi) / 2); if (cmpf(items[mid], items[lo]) < 0) swap(items, lo, mid); if (cmpf(items[hi], items[lo]) < 0) swap(items, lo, hi); if (cmpf(items[mid], items[hi]) < 0) swap(items, mid, hi); return items[hi]; } function partition(items, lo, hi, cmpf) { const pv = pivot(items, lo, hi, cmpf); let i = lo - 1, j = hi + 1; while (i < j) { do i++; while (cmpf(items[i], pv) < 0); do j--; while (cmpf(items[j], pv) > 0); if (i >= j) break; swap(items, i, j); } return j; } function insertionSort(items, left, right, cmpf) { let i, j, key; for (i = left + 1; i <= right; i++) { key = items[i]; j = i - 1; while (j >= left && cmpf(items[j], key) > 0) { items[j + 1] = items[j]; j = j - 1; } items[j + 1] = key; } } function siftDown(items, start, end, cmpf) { let root = start, child, toSwap; while (iLeftChild(root) <= end) { child = iLeftChild(root); toSwap = root; if (cmpf(items[toSwap], items[child]) < 0) toSwap = child; if ((child + 1) <= end && cmpf(items[toSwap], items[child+1]) < 0) toSwap = child + 1; if (toSwap === root) return; swap(items, root, toSwap); root = toSwap; } } function heapify(items, lo, hi, cmpf) { let start = iParent(hi); while (start >= lo) { siftDown(items, start, hi, cmpf); start = start - 1; } } function heapSort(items, lo, hi, cmpf) { heapify(items, lo, hi, cmpf); let end = hi; while (end > lo) { swap(items, end, lo); end = end - 1; siftDown(items, lo, end, cmpf); } } function introSort(items, lo, hi, maxdepth, cmpf) { if (hi - lo < 16) { insertionSort(items, lo, hi, cmpf); return; } if (maxdepth === 0) { heapSort(items, lo, hi, cmpf); return; } const p = partition(items, lo, hi, cmpf); introSort(items, lo, p, maxdepth - 1, cmpf); introSort(items, p + 1, hi, maxdepth - 1, cmpf); } function sort(items, cmpf) { const len = items.length; let maxdepth = Math.floor(Math.log(len)) * 2; introSort(items, 0, len - 1, maxdepth, cmpf); } return { sort, introSort, heapSort, insertionSort }; })(); module.exports = zzosort;