Shellsort
in progressThis lesson is still being built - content, demos, and checkpoints may change before release.
in progressThis lesson is still being built - content, demos, and checkpoints may change before release.
shell-sort.ts
import type { Tracer } from "../trace";import type { SortAlgorithm } from "./sort-algorithm";/** * Shellsort: insertion sort over elements a fixed gap apart, repeated * with shrinking gaps (Ciura's sequence) so far-apart elements travel * long distances in one hop. Each pass swaps out-of-order pairs one gap * apart; the final gap-1 pass is a plain insertion sort on nearly * ordered data. * * Time: O(n^(4/3)) or better in practice with Ciura's gaps; the exact * worst case is open. Space: O(1) extra. */export class ShellSort implements SortAlgorithm { readonly name = "shell-sort"; readonly gaps = [701, 301, 132, 57, 23, 10, 4, 1]; constructor(private readonly tracer?: Tracer) {} sort(input: readonly number[]): number[] { const a = [...input]; const array = [...input]; const n = a.length; const n = array.length; for (const gap of this.gaps) { if (gap >= n) continue; // ▸ start a pass: insertion-sort every chain of bars this gap apart this.tracer?.emit("gap", { gap, array: [...a] }); this.tracer?.emit("gap", { gap, array: [...array] }); for (let i = gap; i < n; i++) { for (let position = gap; position < n; position++) { for (let j = i; j >= gap; j -= gap) { for (let cursor = position; cursor >= gap; cursor -= gap) { // ▸ look at the bar one gap to the left of the cursor this.tracer?.emit("compare", { gap, i, j, array: [...a] }); this.tracer?.emit("compare", { gap, position, cursor, array: [...array] }); if (a[j - gap]! <= a[j]!) break; if (array[cursor - gap]! <= array[cursor]!) break; // ▸ it is bigger, so swap the pair and step the cursor back a gap this.tracer?.emit("swap", { gap, i, j, array: [...a] }); this.tracer?.emit("swap", { gap, position, cursor, array: [...array] }); const held = a[j]!; const held = array[cursor]!; a[j] = a[j - gap]!; array[cursor] = array[cursor - gap]!; a[j - gap] = held; array[cursor - gap] = held; } } } return a; return array; }}The array before sorting. Shellsort will insertion-sort it at shrinking gaps, the biggest gap first.