79 lines
1.7 KiB
TypeScript
79 lines
1.7 KiB
TypeScript
export class PriorityQueue<T> {
|
|
private readonly values: { node: T; priority: number }[] = [];
|
|
|
|
enqueue(node: T, priority: number) {
|
|
this.values.push({ node, priority });
|
|
this._bubbleUp();
|
|
}
|
|
|
|
dequeue() {
|
|
if (this.values.length === 0) return null;
|
|
|
|
const min = this.values[0];
|
|
const end = this.values.pop();
|
|
|
|
if (this.values.length > 0) {
|
|
this.values[0] = end!;
|
|
this._sinkDown();
|
|
}
|
|
|
|
return min;
|
|
}
|
|
|
|
size() {
|
|
return this.values.length;
|
|
}
|
|
|
|
_bubbleUp() {
|
|
let idx = this.values.length - 1;
|
|
const element = this.values[idx];
|
|
|
|
while (idx > 0) {
|
|
const parentIdx = Math.floor((idx - 1) / 2);
|
|
const parent = this.values[parentIdx];
|
|
|
|
if (element.priority >= parent.priority) break;
|
|
|
|
this.values[parentIdx] = element;
|
|
this.values[idx] = parent;
|
|
idx = parentIdx;
|
|
}
|
|
}
|
|
|
|
_sinkDown() {
|
|
let idx = 0;
|
|
const length = this.values.length;
|
|
const element = this.values[0];
|
|
|
|
while (true) {
|
|
const leftChildIdx = 2 * idx + 1;
|
|
const rightChildIdx = 2 * idx + 2;
|
|
let leftChild, rightChild;
|
|
let swap = null;
|
|
|
|
if (leftChildIdx < length) {
|
|
leftChild = this.values[leftChildIdx];
|
|
if (leftChild.priority < element.priority) {
|
|
swap = leftChildIdx;
|
|
}
|
|
}
|
|
|
|
if (rightChildIdx < length) {
|
|
rightChild = this.values[rightChildIdx];
|
|
if (
|
|
(swap === null && rightChild.priority < element.priority) ||
|
|
(swap !== null && rightChild.priority < leftChild!.priority)
|
|
) {
|
|
swap = rightChildIdx;
|
|
}
|
|
}
|
|
|
|
if (swap === null) break;
|
|
|
|
this.values[idx] = this.values[swap];
|
|
this.values[swap] = element;
|
|
idx = swap;
|
|
}
|
|
}
|
|
}
|