UNPKG

js-priority-queue

Version:
112 lines (82 loc) 4.37 kB
Priority Queue ============== A priority queue is a data structure with these operations: | Operation | Syntax (js-priority-queue) | Description | | --------- | --- | ----------- | | Create | `var queue = new PriorityQueue();` | Creates a priority queue | | Queue | `queue.queue(value);` | Inserts a new value in the queue | | Length | `var length = queue.length;` | Returns the number of elements in the queue | | Peek | `var firstItem = queue.peek();` | Returns the smallest item in the queue and leaves the queue unchanged | | Dequeue | `var firstItem = queue.dequeue();` | Returns the smallest item in the queue and removes it from the queue | | Clear | `queue.clear();` | Removes all values from the queue | You cannot access the data in any other way: you must dequeue or peek. Why use this library? Two reasons: 1. It's easier to use than an Array, and it's clearer. 2. It can make your code execute more quickly. Installing ========== You can `npm install js-priority-queue` or `bower install js-priority-queue`. Alternatively, just download `priority-queue.js` from this directory. Include it through [RequireJS](http://requirejs.org/) or [Browserify](http://browserify.org). Or, to pollute your global scope, insert this in your HTML: <script src="priority-queue.js"></script> Then write code like this: var queue = new PriorityQueue({ comparator: function(a, b) { return b - a; }}); queue.queue(5); queue.queue(3); queue.queue(2); var lowest = queue.dequeue(); // returns 5 Options ======= How exactly will these elements be ordered? Let's use the `comparator` option. This is the argument we would pass to [Array.prototype.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort): var compareNumbers = function(a, b) { return a - b; }; var queue = new PriorityQueue({ comparator: compareNumbers }); You can also pass initial values, in any order. With lots of values, it's faster to load them all at once than one at a time. var queue = new PriorityQueue({ initialValues: [ 1, 2, 3 ] }) Strategies ========== We can implement this with a regular `Array`. We'll keep it sorted inversely, so `queue.dequeue()` maps to `array.pop()`. But with an `Array`, we'll need to `splice()`, which can affect every single element in the array. An alternative is to create a [Binary Heap](http://en.wikipedia.org/wiki/Binary_heap), which writes far fewer array elements when queueing (though each element is written more slowly). Finally, we can use a [B-Heap](http://en.wikipedia.org/wiki/B-heap). It's like a binary heap, except it orders elements such that during a single operation, writes occur closer to each other in memory. Unfortunately, it's slower to calculate where in memory each write should occur (it costs a function call instead of a bit-shift). So while it's fast in theory, it's slower in practice. Create the queues like this: var queue = new PriorityQueue({ strategy: PriorityQueue.ArrayStrategy }); // Array var queue = new PriorityQueue({ strategy: PriorityQueue.BinaryHeapStrategy }); // Default var queue = new PriorityQueue({ strategy: PriorityQueue.BHeapStrategy }); // Slower You'll see running times like this: | Operation | Array | Binary heap | B-Heap | | --------- | ----- | ----------- | -------------- | | Create | O(n lg n) | O(n) | O(n) | | Queue | O(n) (often slow) | O(lg n) (fast) | O(lg n) | | Peek | O(1) | O(1) | O(1) | | Dequeue | O(1) (fast) | O(lg n) | O(lg n) | According to [JsPerf](http://jsperf.com/js-priority-queue-queue-dequeue), the fastest strategy for most cases is `BinaryHeapStrategy`. Only use `ArrayStrategy` only if you're queuing items in a very particular order. Don't use `BHeapStrategy`, except as a lesson in how sometimes miracles in one programming language aren't great in other languages. Contributing ============ 1. Fork this repository 2. Run `npm install` 3. Write the behavior you expect in `spec-coffee/` 4. Edit files in `coffee/` until `gulp test` says you're done 5. Run `gulp` to update `priority-queue.js` and `priority-queue.min.js` 6. Submit a pull request License ======= I, Adam Hooper, the sole author of this project, waive all my rights to it and release it under the [Public Domain](http://creativecommons.org/publicdomain/zero/1.0/). Do with it what you will.