/** FIFO with amortized O(1) removal, without Array.shift on each item. */ export function createDeque() { let items: T[] = [], head = 0; return { get size() { return items.length - head; }, push(value: T) { items.push(value); }, peek(): T | undefined { return items[head]; }, pop(): T | undefined { if (head === items.length) return undefined; const value = items[head++]; if (head > 1024 && head * 2 >= items.length) { items = items.slice(head); head = 0; } return value; }, clear() { items = []; head = 0; }, values() { return items.slice(head); }, }; } export function createMinHeap(compare: (left: T, right: T) => number) { const items: T[] = []; return { get size() { return items.length; }, peek(): T | undefined { return items[0]; }, push(value: T) { let index = items.length; items.push(value); while (index > 0) { const parent = (index - 1) >> 1; if (compare(items[parent], value) <= 0) break; items[index] = items[parent]; index = parent; } items[index] = value; }, pop(): T | undefined { if (!items.length) return undefined; const first = items[0], last = items.pop()!; if (items.length) { let index = 0; while (index * 2 + 1 < items.length) { let child = index * 2 + 1; if (child + 1 < items.length && compare(items[child + 1], items[child]) < 0) child++; if (compare(last, items[child]) <= 0) break; items[index] = items[child]; index = child; } items[index] = last; } return first; }, clear() { items.length = 0; }, }; }