function swap(a, i, j, c) {
const t = a[i]; a[i] = a[j]; a[j] = t;
c.writes += 2;
}
function bubbleSort(a, c) {
for (let end = a.length - 1; end > 0; end--) {
let swapped = false;
for (let i = 0; i < end; i++) {
c.cmp++;
if (a[i] > a[i + 1]) { swap(a, i, i + 1, c); swapped = true; }
}
if (!swapped) break; // a pass with no swaps: done early
}
}
function insertionSort(a, c) {
for (let i = 1; i < a.length; i++) {
const x = a[i];
let j = i - 1;
while (j >= 0) {
c.cmp++;
if (a[j] <= x) break;
a[j + 1] = a[j]; c.writes++; // shift the bigger one right
j--;
}
a[j + 1] = x; c.writes++;
}
}
function mergeSort(a, c, lo = 0, hi = a.length - 1) {
if (lo >= hi) return;
const mid = (lo + hi) >> 1;
mergeSort(a, c, lo, mid); // sort the left half
mergeSort(a, c, mid + 1, hi); // sort the right half
const left = a.slice(lo, mid + 1), right = a.slice(mid + 1, hi + 1);
let i = 0, j = 0, k = lo; // merge them back, smallest first
while (i < left.length && j < right.length) {
c.cmp++;
a[k++] = left[i] <= right[j] ? left[i++] : right[j++]; c.writes++;
}
while (i < left.length) { a[k++] = left[i++]; c.writes++; }
while (j < right.length) { a[k++] = right[j++]; c.writes++; }
}
function quickSort(a, c, lo = 0, hi = a.length - 1) {
if (lo >= hi) return;
const pivot = a[hi]; // Lomuto partition: last item is the pivot
let p = lo;
for (let i = lo; i < hi; i++) {
c.cmp++;
if (a[i] < pivot) { swap(a, i, p, c); p++; }
}
swap(a, p, hi, c); // the pivot lands in its final place
quickSort(a, c, lo, p - 1);
quickSort(a, c, p + 1, hi);
}
function heapSort(a, c) {
const n = a.length;
for (let i = (n >> 1) - 1; i >= 0; i--) siftDown(a, i, n, c); // build a max-heap
for (let end = n - 1; end > 0; end--) {
swap(a, 0, end, c); // the biggest goes to the back
siftDown(a, 0, end, c);
}
}
function siftDown(a, i, n, c) {
while (true) {
const l = 2 * i + 1, r = l + 1;
let big = i;
if (l < n) { c.cmp++; if (a[l] > a[big]) big = l; }
if (r < n) { c.cmp++; if (a[r] > a[big]) big = r; }
if (big === i) return;
swap(a, i, big, c);
i = big;
}
}
const data = [17, 4, 22, 9, 1, 14, 20, 6, 11, 24, 3, 15, 8, 19, 2, 13, 23, 10, 5, 18, 12, 21, 7, 16];
const results = [];
for (const [name, sort] of [["bubble", bubbleSort], ["insertion", insertionSort],
["merge", mergeSort], ["quick", quickSort], ["heap", heapSort]]) {
const a = data.slice(); // every sort gets the same copy
const c = { cmp: 0, writes: 0 };
sort(a, c);
results.push({ name, comparisons: c.cmp, writes: c.writes, sorted: a.join() === data.slice().sort((x, y) => x - y).join() });
}
console.table(results);