s2-tools
Version:
A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.
113 lines • 2.96 kB
JavaScript
/**
* # Priority Queue
*
* ## Description
* A priority queue is a data structure that stores elements in a specific order.
*
* ## Usage
*
* ```ts
* import { PriorityQueue } from 's2-tools';
*
* const queue = new PriorityQueue<number>();
*
* queue.push(1);
* queue.push(2);
*
* const current = queue.peek(); // 1
* console.log(queue.length); // 2
* let next = queue.pop(); // 1
* console.log(queue.length); // 1
* next = queue.pop(); // 2
* console.log(queue.length); // 0
* ```
*/
export class PriorityQueue {
data;
compare;
#length = 0;
/**
* @param data - initial data
* @param compare - compare function
*/
constructor(data = [], compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0)) {
this.data = data;
this.compare = compare;
this.#length = data.length;
if (this.#length > 0) {
for (let i = (this.#length >> 1) - 1; i >= 0; i--)
this.#down(i);
}
}
/** @returns - the number of items */
get length() {
return this.#length;
}
/**
* Push an item into the queue
* @param item - the item to store
*/
push(item) {
this.data.push(item);
this.#up(this.#length++);
}
/**
* Access the top item, remove it, and return it
* @returns - the top item
*/
pop() {
if (this.#length === 0)
return;
const top = this.data.at(0);
const bottom = this.data.pop();
if (bottom === undefined)
return;
if (--this.#length > 0) {
this.data[0] = bottom;
this.#down(0);
}
return top;
}
/**
* Peek at the top item without removing it
* @returns - the top item
*/
peek() {
return this.data.at(0);
}
/**
* @param pos - the position to reorder
*/
#up(pos) {
const { data, compare } = this;
const item = data[pos];
while (pos > 0) {
const parent = (pos - 1) >> 1;
const current = data[parent];
if (compare(item, current) >= 0)
break;
data[pos] = current;
pos = parent;
}
data[pos] = item;
}
/** @param pos - the position to start reordering */
#down(pos) {
const { data, compare } = this;
const halfLength = this.#length >> 1;
const item = data[pos];
while (pos < halfLength) {
let bestChild = (pos << 1) + 1; // initially it is the left child
const right = bestChild + 1;
if (right < this.#length && compare(data[right], data[bestChild]) < 0) {
bestChild = right;
}
if (compare(data[bestChild], item) >= 0)
break;
data[pos] = data[bestChild];
pos = bestChild;
}
data[pos] = item;
}
}
//# sourceMappingURL=priorityQueue.js.map