class BHeap {
constructor(score, compare=null) {
this._arr = [];
this.score = score;
this.compare = compare ? compare : (a,b) => a >= b;
}
push(x) {
this._arr.push(x);
this.bubbleUp(this._arr.length-1);
}
pop() {
const result = this._arr[0];
const last = this._arr.pop();
if (this._arr.length > 0) {
this._arr[0] = last;
this.bubbleDown(0);
}
return result;
}
size() {
return this._arr.length;
}
bubbleUp(n) {
const val = this._arr[n];
const score = this.score(val);
while (n > 0) {
const parentN = Math.floor((n+1)/2) - 1;
const parent = this._arr[parentN];
if (this.compare(score, this.score(parent))) break;
this._arr[parentN] = val;
this._arr[n] = parent;
n = parentN;
}
}
bubbleDown(n) {
const length = this._arr.length;
const val = this._arr[n];
const score = this.score(val);
while (true) {
const child2N = 2*(n+1);
const child1N = child2N-1;
let swap = null;
let child1,
child1score;
if (child1N < length) {
child1 = this._arr[child1N];
child1score = this.score(child1);
if (!this.compare(child1score, score)) {
swap = child1N;
}
}
if (child2N < length) {
const child2 = this._arr[child2N];
const child2score = this.score(child2);
if (!this.compare(child2score, (swap === null ? score : child1score))) {
swap = child2N;
}
}
if (swap === null) break;
this._arr[n] = this._arr[swap];
this._arr[swap] = val;
n = swap;
}
}
}