class PriorityQueue {
constructor(
compare = (a, b) => a[0] < b[0]
){
this.data = []
this.size = 0
this.compare = compare
}
peek() {
return this.size === 0 ? null : this.data[0]
}
offer(val) {
this.data.push(val)
this._shifUp(this.size++)
}
poll() {
if(this.size === 0) { return null }
this._swap(0, --this.size)
this._shifDown(0)
return this.data.pop()
}
_parent(index) {
return index - 1 >> 1
}
_child(index) {
return (index << 1) + 1
}
_shifDown(index) {
while(this._child(index) < this.size) {
let child = this._child(index)
if(child + 1 < this.size
&& this.compare(this.data[child + 1], this.data[child])) {
child = child + 1
}
if(this.compare(this.data[index], this.data[child])){
break
}
this._swap(index, child)
index = child
}
}
_shifUp(index) {
while(this._parent(index) >= 0
&& this.compare(this.data[index], this.data[this._parent(index)])) {
this._swap(index, this._parent(index))
index = this._parent(index)
}
}
_swap(a, b) {
[this.data[a], this.data[b]] = [this.data[b], this.data[a]]
}
}