2019-07-07 22:28:38 +00:00
|
|
|
class MinHeap {
|
|
|
|
|
constructor(valueFunc=(a) => a) {
|
|
|
|
|
this.valueFunc_ = valueFunc;
|
|
|
|
|
this.data_ = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
push(...vals) {
|
|
|
|
|
for (let val of vals) {
|
|
|
|
|
this.data_.push(val);
|
|
|
|
|
this.bubbleUp_();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pop() {
|
|
|
|
|
let min = this.data_[0];
|
|
|
|
|
if (this.data_.length > 1) {
|
|
|
|
|
this.data_[0] = this.data_.pop();
|
|
|
|
|
this.bubbleDown_();
|
|
|
|
|
} else {
|
|
|
|
|
this.data_.length = 0;
|
|
|
|
|
}
|
|
|
|
|
return min;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bubbleUp_() {
|
|
|
|
|
for (let idx = this.data_.length - 1; idx > 0;) {
|
|
|
|
|
let parent = Math.floor((idx + 1) / 2) - 1;
|
|
|
|
|
|
|
|
|
|
if (this.valueFunc_(this.data_[parent]) >
|
|
|
|
|
this.valueFunc_(this.data_[idx])) {
|
|
|
|
|
[this.data_[parent], this.data_[idx]] =
|
|
|
|
|
[this.data_[idx], this.data_[parent]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
idx = parent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bubbleDown_() {
|
|
|
|
|
for (let idx = 0;;) {
|
|
|
|
|
let children = [
|
|
|
|
|
(idx + 1) * 2,
|
|
|
|
|
(idx + 1) * 2 - 1,
|
|
|
|
|
];
|
|
|
|
|
let toSwap = idx;
|
|
|
|
|
|
|
|
|
|
// Find the minimum value of the current node and its two children
|
|
|
|
|
for (let child of children) {
|
2019-07-07 22:47:23 +00:00
|
|
|
if (this.data_[child] != undefined &&
|
2019-07-07 22:28:38 +00:00
|
|
|
this.valueFunc_(this.data_[child]) <
|
|
|
|
|
this.valueFunc_(this.data_[toSwap])) {
|
|
|
|
|
toSwap = child;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (toSwap == idx) {
|
|
|
|
|
// Current node is smaller than both children; tree is correct
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[this.data_[toSwap], this.data_[idx]] =
|
|
|
|
|
[this.data_[idx], this.data_[toSwap]];
|
|
|
|
|
|
|
|
|
|
idx = toSwap;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|