From 660722490fdb29e9e43a5e7942173ef3baf01249 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Mon, 23 Oct 2017 13:57:13 +0200 Subject: [PATCH] specialized array sort is back (because ordered sets need it) --- src/structure/collections/sort.ts | 62 ++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/structure/collections/sort.ts b/src/structure/collections/sort.ts index 92ac607ac..86525401a 100644 --- a/src/structure/collections/sort.ts +++ b/src/structure/collections/sort.ts @@ -83,12 +83,72 @@ function quickSort(ctx: Ctx, low: number, high: number) { } } +function partitionArrayAsc(data: number[], parts: number[], l: number, r: number) { + let equals = l + 1, tail = r; + + // move the median to the 1st spot + arraySwap(data, l, medianPivotIndex(data, arrayLess, l, r)); + const pivot = data[l]; + + while (data[tail] > pivot) { --tail; } + for (let i = l + 1; i <= tail; i++) { + const v = data[i]; + if (v > pivot) { + arraySwap(data, i, tail); + --tail; + while (data[tail] > pivot) { --tail; } + i--; + } else if (v === pivot) { + arraySwap(data, i, equals); + ++equals; + } + } + + // move all medians to the correct spots + for (let i = l; i < equals; i++) { arraySwap(data, i, l + tail - i); } + parts[0] = tail - equals + l + 1; + parts[1] = tail; +} + +function insertionSortArrayAsc(data: number[], start: number, end: number) { + for (let i = start + 1; i <= end; i++) { + const key = data[i]; + let j = i - 1; + while (j >= start && data[j] > key) { + data[j + 1] = data[j]; + j = j - 1; + } + data[j + 1] = key; + } +} + +function quickSortArrayAsc(data: number[], parts: number[], low: number, high: number) { + while (low < high) { + if (high - low < 16) { + insertionSortArrayAsc(data, low, high); + return; + } + + partitionArrayAsc(data, parts, low, high); + const li = parts[0], ri = parts[1]; + + if (li - low < high - ri) { + quickSortArrayAsc(data, parts, low, li - 1); + low = ri + 1; + } else { + quickSortArrayAsc(data, parts, ri + 1, high); + high = li - 1; + } + } +} + export function sortArray(data: ArrayLike<number>, cmp: Comparer<ArrayLike<number>> = arrayLess): ArrayLike<number> { return sortArrayRange(data, 0, data.length, cmp); } export function sortArrayRange(data: ArrayLike<number>, start: number, end: number, cmp: Comparer<ArrayLike<number>> = arrayLess): ArrayLike<number> { - quickSort({ data, cmp, swap: arraySwap, parts: [0, 0] }, start, end - 1); + if (cmp === arrayLess) quickSortArrayAsc(data as any, [0, 0], start, end - 1); + else quickSort({ data, cmp, swap: arraySwap, parts: [0, 0] }, start, end - 1); return data; } -- GitLab