export class PriorityQueue { private readonly values: { node: T; priority: number }[] = []; enqueue(node: T, priority: number) { this.values.push({ node, priority }); this._bubbleUp(); } dequeue() { if (this.values.length === 0) return null; const min = this.values[0]; const end = this.values.pop(); if (this.values.length > 0) { this.values[0] = end!; this._sinkDown(); } return min; } size() { return this.values.length; } _bubbleUp() { let idx = this.values.length - 1; const element = this.values[idx]; while (idx > 0) { const parentIdx = Math.floor((idx - 1) / 2); const parent = this.values[parentIdx]; if (element.priority >= parent.priority) break; this.values[parentIdx] = element; this.values[idx] = parent; idx = parentIdx; } } _sinkDown() { let idx = 0; const length = this.values.length; const element = this.values[0]; while (true) { const leftChildIdx = 2 * idx + 1; const rightChildIdx = 2 * idx + 2; let leftChild, rightChild; let swap = null; if (leftChildIdx < length) { leftChild = this.values[leftChildIdx]; if (leftChild.priority < element.priority) { swap = leftChildIdx; } } if (rightChildIdx < length) { rightChild = this.values[rightChildIdx]; if ( (swap === null && rightChild.priority < element.priority) || (swap !== null && rightChild.priority < leftChild!.priority) ) { swap = rightChildIdx; } } if (swap === null) break; this.values[idx] = this.values[swap]; this.values[swap] = element; idx = swap; } } }