export type HeapNode = { element: T child?: HeapNode next?: HeapNode prev?: HeapNode } | null | undefined; // minimal pairing heap priority queue implementation export class PairingHeap { private root: HeapNode = null; private comparator: (a: T, b: T) => boolean; // comparator function should return 'true' if a is higher priority than b constructor(comparator: (a: T, b: T) => boolean) { this.comparator = comparator; } isEmpty(): boolean { return !this.root; } add(element: T): HeapNode { const node: HeapNode = { element }; this.root = this.meld(this.root, node); return node; } // returns the top priority element without modifying the queue peek(): T | void { return this.root?.element; } // removes and returns the top priority element pop(): T | void { let element; if (this.root) { const node = this.root; element = node.element; this.root = this.mergePairs(node.child); } return element; } deleteNode(node: HeapNode): void { if (!node) { return; } if (node === this.root) { this.root = this.mergePairs(node.child); } else { if (node.prev) { if (node.prev.child === node) { node.prev.child = node.next; } else { node.prev.next = node.next; } } if (node.next) { node.next.prev = node.prev; } this.root = this.meld(this.root, this.mergePairs(node.child)); } node.child = null; node.prev = null; node.next = null; } // fix the heap after increasing the priority of a given node increasePriority(node: HeapNode): void { // already the top priority element if (!node || node === this.root) { return; } // extract from siblings if (node.prev) { if (node.prev?.child === node) { if (this.comparator(node.prev.element, node.element)) { // already in a valid position return; } node.prev.child = node.next; } else { node.prev.next = node.next; } } if (node.next) { node.next.prev = node.prev; } this.root = this.meld(this.root, node); } decreasePriority(node: HeapNode): void { this.deleteNode(node); this.root = this.meld(this.root, node); } meld(a: HeapNode, b: HeapNode): HeapNode { if (!a) { return b; } if (!b || a === b) { return a; } let parent: HeapNode = b; let child: HeapNode = a; if (this.comparator(a.element, b.element)) { parent = a; child = b; } child.next = parent.child; if (parent.child) { parent.child.prev = child; } child.prev = parent; parent.child = child; parent.next = null; parent.prev = null; return parent; } mergePairs(node: HeapNode): HeapNode { if (!node) { return null; } let current: HeapNode = node; let next: HeapNode; let nextCurrent: HeapNode; let pairs: HeapNode; let melded: HeapNode; while (current) { next = current.next; if (next) { nextCurrent = next.next; melded = this.meld(current, next); if (melded) { melded.prev = pairs; } pairs = melded; } else { nextCurrent = null; current.prev = pairs; pairs = current; break; } current = nextCurrent; } melded = null; let prev: HeapNode; while (pairs) { prev = pairs.prev; melded = this.meld(melded, pairs); pairs = prev; } return melded; } }