gis-tools-ts
Version:
A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.
116 lines • 3.66 kB
JavaScript
/**
* # FlatQueue
*
* ## Description
* A priority queue implemented using a binary heap.
*
* A Typescript port from the [flatqueue](https://github.com/mourner/flatqueue) code.
*
* ## Usage
*
* ```ts
* import { FlatQueue } from 'gis-tools-ts';
*
* const queue = new FlatQueue<number>();
*
* queue.push(0, 2);
* queue.push(1, 1);
* queue.push(2, 3);
*
* expect(queue.pop()).toEqual(2);
* expect(queue.pop()).toEqual(1);
* expect(queue.pop()).toEqual(0);
* ```
*/
export class FlatQueue {
#ids = [];
#values = [];
#length = 0;
/** @returns - the number of items */
get length() {
return this.#length;
}
/** Removes all items from the queue. */
clear() {
this.#length = 0;
}
/**
* Adds `item` to the queue with the specified `priority`.
*
* `priority` must be a number. Items are sorted and returned from low to high priority. Multiple items
* with the same priority value can be added to the queue, but there is no guaranteed order between these items.
* @param item - the item to add
* @param priority - the priority of the item
*/
push(item, priority) {
let pos = this.#length++;
while (pos > 0) {
const parent = (pos - 1) >> 1;
const parentValue = this.#values[parent];
if (priority >= parentValue)
break;
this.#ids[pos] = this.#ids[parent];
this.#values[pos] = parentValue;
pos = parent;
}
this.#ids[pos] = item;
this.#values[pos] = priority;
}
/**
* Removes and returns the item from the head of this queue, which is one of
* the items with the lowest priority. If this queue is empty, returns `undefined`.
* @returns the item from the head of this queue
*/
pop() {
if (this.#length === 0)
return undefined;
const ids = this.#ids;
const values = this.#values;
const top = ids[0];
const last = --this.#length;
if (last > 0) {
const id = ids[last];
const value = values[last];
let pos = 0;
const halfLen = last >> 1;
while (pos < halfLen) {
const left = (pos << 1) + 1;
const right = left + 1;
const child = left + (Number(right < last) & Number(values[right] < values[left]));
if (values[child] >= value)
break;
ids[pos] = ids[child];
values[pos] = values[child];
pos = child;
}
ids[pos] = id;
values[pos] = value;
}
return top;
}
/**
* @returns the item from the head of this queue without removing it. If this queue is empty,
* returns `undefined`.
*/
peek() {
return this.length > 0 ? this.#ids[0] : undefined;
}
/**
* @returns the priority value of the item at the head of this queue without
* removing it. If this queue is empty, returns `undefined`.
*/
peekValue() {
return this.length > 0 ? this.#values[0] : undefined;
}
/**
* Shrinks the internal arrays to `this.length`.
*
* `pop()` and `clear()` calls don't free memory automatically to avoid unnecessary resize operations.
* This also means that items that have been added to the queue can't be garbage collected until
* a new item is pushed in their place, or this method is called.
*/
shrink() {
this.#ids.length = this.#values.length = this.length;
}
}
//# sourceMappingURL=flatqueue.js.map