|
@@ -7,12 +7,7 @@
|
|
|
export type Comparer<T = any> = (data: T, i: number, j: number) => number
|
|
|
export type Swapper<T = any> = (data: T, i: number, j: number) => void
|
|
|
|
|
|
-type Ctx = {
|
|
|
- cmp: Comparer,
|
|
|
- swap: Swapper,
|
|
|
- parts: number[],
|
|
|
- data: any
|
|
|
-}
|
|
|
+type Ctx = { cmp: Comparer, swap: Swapper, parts: number[], data: any }
|
|
|
|
|
|
export function arrayLess(arr: ArrayLike<number>, i: number, j: number) {
|
|
|
return arr[i] - arr[j];
|
|
@@ -30,7 +25,7 @@ function medianPivotIndex(data: any, cmp: Comparer, l: number, r: number) {
|
|
|
else return cmp(data, r, m) > 0 ? cmp(data, m, l) > 0 ? m : l : r;
|
|
|
}
|
|
|
|
|
|
-function partitionGeneric(ctx: Ctx, l: number, r: number) {
|
|
|
+function partition(ctx: Ctx, l: number, r: number) {
|
|
|
const { cmp, swap, data, parts } = ctx;
|
|
|
let equals = l + 1, tail = r;
|
|
|
|
|
@@ -57,33 +52,6 @@ function partitionGeneric(ctx: Ctx, l: number, r: number) {
|
|
|
parts[1] = tail;
|
|
|
}
|
|
|
|
|
|
-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 insertionSort({ data, cmp, swap }: Ctx, start: number, end: number) {
|
|
|
for (let i = start + 1; i <= end; i++) {
|
|
|
let j = i - 1;
|
|
@@ -102,7 +70,7 @@ function quickSort(ctx: Ctx, low: number, high: number) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- partitionGeneric(ctx, low, high);
|
|
|
+ partition(ctx, low, high);
|
|
|
const li = parts[0], ri = parts[1];
|
|
|
|
|
|
if (li - low < high - ri) {
|
|
@@ -115,46 +83,17 @@ function quickSort(ctx: Ctx, low: number, high: number) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-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 sortArray(data: ArrayLike<number>, cmp: Comparer<ArrayLike<number>> = arrayLess): ArrayLike<number> {
|
|
|
- if (cmp === arrayLess) quickSortArrayAsc(data as any, [0, 0], 0, data.length - 1);
|
|
|
- else quickSort({ data, cmp, swap: arraySwap, parts: [0, 0] }, 0, data.length - 1);
|
|
|
+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);
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
-export function sort<T>(data: T, count: number, cmp: Comparer<T>, swap: Swapper<T>): T {
|
|
|
+export function sort<T>(data: T, start: number, end: number, cmp: Comparer<T>, swap: Swapper<T>): T {
|
|
|
const ctx: Ctx = { data, cmp, swap, parts: [0, 0] };
|
|
|
- quickSort(ctx, 0, count - 1);
|
|
|
+ quickSort(ctx, start, end - 1);
|
|
|
return data;
|
|
|
}
|