Binary Min-Heap Priority Queue
Implement a dependency-free binary min-heap with a custom comparator for O(log n) priority queue pushes and pops.
Code
export class MinHeap {
#items = [];
#compare;
constructor(compare = (left, right) => left - right) {
if (typeof compare !== "function") {
throw new TypeError("compare must be a function");
}
this.#compare = compare;
}
get size() {
return this.#items.length;
}
get isEmpty() {
return this.#items.length === 0;
}
peek() {
return this.#items[0];
}
push(value) {
this.#items.push(value);
this.#bubbleUp(this.#items.length - 1);
return this;
}
pop() {
if (this.#items.length === 0) return undefined;
const root = this.#items[0];
const last = this.#items.pop();
if (this.#items.length > 0) {
this.#items[0] = last;
this.#sinkDown(0);
}
return root;
}
#bubbleUp(startIndex) {
let index = startIndex;
while (index > 0) {
const parentIndex = (index - 1) >> 1;
if (this.#compare(this.#items[index], this.#items[parentIndex]) >= 0) {
break;
}
const current = this.#items[index];
this.#items[index] = this.#items[parentIndex];
this.#items[parentIndex] = current;
index = parentIndex;
}
}
#sinkDown(startIndex) {
let index = startIndex;
const length = this.#items.length;
while (true) {
const left = index * 2 + 1;
const right = left + 1;
let smallest = index;
if (
left < length &&
this.#compare(this.#items[left], this.#items[smallest]) < 0
) {
smallest = left;
}
if (
right < length &&
this.#compare(this.#items[right], this.#items[smallest]) < 0
) {
smallest = right;
}
if (smallest === index) break;
const current = this.#items[index];
this.#items[index] = this.#items[smallest];
this.#items[smallest] = current;
index = smallest;
}
}
static from(values, compare) {
if (values == null || typeof values[Symbol.iterator] !== "function") {
throw new TypeError("values must be iterable");
}
const heap = new MinHeap(compare);
for (const value of values) heap.push(value);
return heap;
}
}
const queue = new MinHeap(
(left, right) => left.priority - right.priority || left.sequence - right.sequence,
);
const tasks = [
{ name: "send-email", priority: 2, sequence: 1 },
{ name: "rotate-logs", priority: 3, sequence: 2 },
{ name: "charge-card", priority: 1, sequence: 3 },
{ name: "warm-cache", priority: 2, sequence: 4 },
];
for (const task of tasks) queue.push(task);
while (!queue.isEmpty) {
const task = queue.pop();
console.log(task.priority, task.name);
}
const numbers = MinHeap.from([5, 1, 4, 2, 3]);
const sorted = [];
while (!numbers.isEmpty) sorted.push(numbers.pop());
console.log(sorted.join(","));Report a problem with this exampleOpens a pre-filled issue on GitHub.