class BHeap {
constructor(weightfunc) {
this.weightfunc = weightfunc;
this.arr = [];
this.dbg = "";
}
debug(s) {
this.dbg = `${this.dbg}${s}\n`;
}
getDbg() { return this.dbg; }
parentI(i) {
return Math.floor((i-1)/2);
}
lchildI(i) {
return (2*i)+1;
}
rchildI(i) {
return (2*i)+2;
}
add(item) {
if (this.weightfunc) {
let weight = this.weightfunc(item);
let obj = {
item,
weight
};
this.arr.push(obj);
this.percUp(this.arr.length-1, obj);
} else {
this.arr.push(item);
this.percUp(this.arr.length-1, item);
}
}
addAll(...items) {
for (let i of items) {
if (i.length != undefined) {
for (let it of i) {
this.add(it);
}
} else {
this.add(i);
}
}
}
lt(a, b) {
if (this.weightfunc)
return a.weight < b.weight
else return a < b;
}
popMin() {
let min = this.arr[0];
if (this.arr.length > 1) {
this.percDown(0, this.arr.pop());
} else {
this.arr.pop()
}
return this.weightfunc ? min.item : min;
}
percDown(i, value) {
let N = this.arr.length;
if (this.lchildI(i) >= N) {
this.arr[i] = value;
} else if (this.lchildI(i) == (N-1)) {
if (this.lt(this.arr[this.lchildI(i)], value)) {
this.arr[i] = this.arr[this.lchildI(i)];
this.arr[this.lchildI(i)] = value;
} else {
this.arr[i] = value;
}
} else {
let j = 0;
if (this.lt(this.arr[this.lchildI(i)], this.arr[this.rchildI(i)]))
j = this.lchildI(i);
else
j = this.rchildI(i);
if (this.lt(this.arr[j], value)) {
this.arr[i] = this.arr[j];
this.percDown(j, value);
} else {
this.arr[i] = value;
}
}
}
percUp(i, value) {
if (i == 0) {
this.arr[i] = value;
} else if (this.lt(this.arr[this.parentI(i)], value)) {
this.arr[i] = value;
} else {
this.arr[i] = this.arr[this.parentI(i)];
this.percUp(this.parentI(i), value);
}
}
peekMin() {
return this.weightfunc ? this.arr[0].item : this.arr[0];
}
getRaw() {
return this.arr
}
get length() {
return this.arr.length;
}
}