79 lines
1.6 KiB
JavaScript
79 lines
1.6 KiB
JavaScript
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
|
|
}
|
|
}
|
|
}
|