import { asAsyncComparer } from "./comparer/async.js"; import { MaybeAsyncComparisonOrComparer, AsyncComparer } from "./comparer/types.js"; export interface AsyncSorter { sort(array: T[], descending: boolean, comparer: MaybeAsyncComparisonOrComparer): Promise; } function swap(array: any[], i: number, j: number) { const tmp = array[i]; array[i] = array[j]; array[j] = tmp; } abstract class BaseAsyncSorter implements AsyncSorter { async sort(array: T[], descending: boolean, comparer: MaybeAsyncComparisonOrComparer) { comparer = asAsyncComparer(comparer); if (descending) { comparer = comparer.reverse(); } await this._sort(array, comparer); } protected abstract _sort(array: T[], comparer: AsyncComparer): Promise; } export const insertionSorter: AsyncSorter = new class InsertionSorter extends BaseAsyncSorter { protected override async _sort(array: T[], comparer: AsyncComparer) { for (let i = 1; i < array.length; i++) { const obj = array[i]; for (let j = i - 1; j >= 0; j--) { if (await comparer.compare(obj, array[j]) < 0) { for (let k = i; k > j; k--) { swap(array, k - 1, k); } break; } } } } }; export const selectionSorter: AsyncSorter = new class SelectionSorter extends BaseAsyncSorter { protected async _sort(array: T[], comparer: AsyncComparer) { for (let i = 0; i < array.length; i++) { let smallest = array[i]; let smallestIndex = i; for (let j = i; j < array.length; j++) { const current = array[j]; if (await comparer.compare(current, smallest) < 0) { smallest = current; smallestIndex = j; } } if (smallestIndex !== i) { swap(array, smallestIndex, i); } } } }; export const bubbleSorter: AsyncSorter = new class BubbleSorter extends BaseAsyncSorter { protected async _sort(array: T[], comparer: AsyncComparer) { const length = array.length; for (let k = length - 2; k >= 0; k--) { let hasSwaped = false; for (let i = 0; i <= k; i++) { const j = i + 1; const a = array[i], b = array[j]; if (await comparer.compare(a, b) > 0) { swap(array, i, j); hasSwaped = true; } } if (!hasSwaped) { break; } } } };