🚑 🚴 🚌 🚕 🚗 🚚 🚛
A very fast JavaScript priority queue, implemented using a binary heap, which in turn is implemented using two underlying parallel typed arrays. No dependencies whatsoever; just plain, vanilla JS.
It's the fastest publicly available JavaScript library implementation of a priority queue. Here's an average benchmark comparing Heapify with TinyQueue and FlatQueue, running for 1 million elements:
build push pop push+pop
TinyQueue 110ms 110ms 624ms 205ms
FlatQueue 85ms 85ms 157ms 112ms
Heapify 32ms 41ms 150ms 112ms
Host machine: 2.4 GHz Dual-Core Intel Core i7, 16 GB RAM.
Note: the build operation doesn't actually exist in TinyQueue and FlatQueue, so it has to be replaced with a manual push operation. That's why build times for those two cases are the same as for push.
Supported queue operations:
- push: O(log n)
- pop: O(log n)
- peek: O(1)
- creation with pre-existing list of priorities: O(n)
Other features:
- runs on browser and Node.js with support to ES6 modules
- tiny code base (under 200 LoC)
- no dependencies
- supports several types of priorities and keys
npm i heapify
Or if you're a yarn person:
yarn add heapify
If you're on a browser, there's also the option of using a CDN:
import Heapify from "https://unpkg.com/heapify"
And to import a specific version:
import Heapify from "https://unpkg.com/[email protected]"
import Heapify from "heapify";
const queue = new Heapify();
queue.push(1, 10);
queue.push(2, 5);
queue.pop(); // 2
queue.peek(); // 1
queue.clear();
queue.pop(); // undefined
See the API section below for more details.
You are welcome to contribute, but please take the time to read and follow these guidelines.
new Heapify(capacity = 64, keys = [], priorities = [], KeysBackingArrayType = Uint32Array, PrioritiesBackingArrayType = Uint32Array)
Creates a new priority queue. Parameters are:
capacity
: the size of the underlying typed arrays backing the heap;keys
: an optional array of pre-existing keys. Provide[]
to skip this field;priorities
: an optional array of pre-existing priorities. Must match number of keys above. Provide[]
to skip this field;KeysBackingArrayType
: the array type to be used for keys;PrioritiesBackingArrayType
: the array type to be used for priorities.
Example:
const queue1 = new Heapify(32);
const queue2 = new Heapify(16, [], [], Uint64Array, Uint32Array);
Effectively empties the queue. The heap capacity is not changed, nor its elements get erased in any way; it's just the variable that tracks the length that gets cleared to zero, so it's a very cheap operation.
Example:
const queue = new Heapify();
queue.push(1, 10);
console.info(queue.length); // 1
queue.clear();
console.info(queue.length); // 0
Gets the key with the smallest priority, but does not remove it from the queue.
Example:
const queue = new Heapify();
queue.push(1, 10);
queue.peek(); // 1
Gets the priority of the key with the smallest priority, but does not remove the item from the queue.
Example:
const queue = new Heapify();
queue.push(1, 10);
queue.peekPriority(); // 10
Removes the smallest priority item from the queue, returning its key.
Example:
const queue = new Heapify();
queue.push(1, 10);
queue.pop(); // 1
Adds a new item to the queue with a given key
and priority
. Will throw an error if the queue is already at its capacity.
Example:
const queue = new Heapify();
queue.push(1, 10);
queue.length; // 1
queue.peek(); // 1
queue.peekPriority(); // 10
Returns a string with an array representation of all priorities in the queue. For instance, given the following priority heap:
10
30 20
40
The returned string will be [10 30 20 40]
. See tests for more examples.
Allows to get an iterator that iterates over keys and priorities that will be yielded as tuples ([key, priority]
):
const queue = new Heapify();
queue.push(5, 35);
queue.push(3, 30);
queue.push(1, 10);
queue.push(2, 20);
queue.push(4, 40);
console.log([...queue]) // [ [ 1, 10 ], [ 2, 20 ], [ 3, 30 ], [ 5, 35 ], [ 4, 40 ] ]
You can also use this feature conveniently with a for ... of
construct:
const queue = new Heapify();
queue.push(5, 35);
queue.push(3, 30);
queue.push(1, 10);
queue.push(2, 20);
queue.push(4, 40);
for (const [key, priority] of queue) {
console.log(key, priority)
}
// 1 10
// 2 20
// 3 30
// 5 35
// 4 40
Allows to get an iterator that iterates over keys:
const queue = new Heapify();
queue.push(5, 35);
queue.push(3, 30);
queue.push(1, 10);
queue.push(2, 20);
queue.push(4, 40);
console.log([...queue.keys()]); // [ 1, 2, 3, 5, 4 ]
Allows to get an iterator that iterates over keys:
const queue = new Heapify();
queue.push(5, 35);
queue.push(3, 30);
queue.push(1, 10);
queue.push(2, 20);
queue.push(4, 40);
console.log([...queue.priorities()]); // [ 10, 20, 30, 35, 40 ]