const top = 0; const parent = i => ((i + 1) >>> 1) - 1; const left = i => (i << 1) + 1; const right = i => (i + 1) << 1; export default class PriorityQueue { #heap #comparator constructor(comparator = (a, b) => a > b) { this.#heap = [] this.#comparator = comparator } get length() { return this.#heap.length } isEmpty() { return this.length < 1 } peek() { return this.#heap[top] } push(...values) { values.forEach(value => { this.#heap.push(value) this.#siftUp(); }); return this.length; } pop() { const poppedValue = this.peek() const bottom = this.length - 1 if (bottom > top) { this.#swap(top, bottom) } this.#heap.pop() this.#siftDown() return poppedValue } replace(value) { const replacedValue = this.peek() this.#heap[top] = value this.#siftDown() return replacedValue } #greater(i, j) { return this.#comparator(this.#heap[i], this.#heap[j]) } #swap(i, j) { [this.#heap[i], this.#heap[j]] = [this.#heap[j], this.#heap[i]] } #siftUp() { let node = this.length - 1 while (node > top && this.#greater(node, parent(node))) { this.#swap(node, parent(node)) node = parent(node) } } #siftDown() { let node = top; while ( (left(node) < this.length && this.#greater(left(node), node)) || (right(node) < this.length && this.#greater(right(node), node)) ) { let maxChild = (right(node) < this.length && this.#greater(right(node), left(node))) ? right(node) : left(node) this.#swap(node, maxChild) node = maxChild } } }