UNPKG

dagre-d3-es

Version:

<p align="center"> <a href="https://tbo47.github.io/" ><img src="https://img.shields.io/badge/created_by-tbo47-blue.svg" alt="Created by tbo47"></a> <a href="https://www.npmjs.com/dagre-d3-es"><img src="https://img.shields.io/npm/v/dagre-d3-es.svg?log

180 lines (178 loc) 4.83 kB
export { PriorityQueue }; /** * A min-priority queue data structure. This algorithm is derived from Cormen, * et al., "Introduction to Algorithms". The basic idea of a min-priority * queue is that you can efficiently (in O(1) time) get the smallest key in * the queue. Adding and removing elements takes O(log n) time. A key can * have its priority decreased in O(log n) time. */ class PriorityQueue { constructor() { /** * @private * @type {Array<{key: string, priority: number}>} */ this._arr = []; /** * @private * @type {Record<string, number>} */ this._keyIndices = {}; } /** * @returns {number} the number of elements in the queue. * @remarks Takes `O(1)` time. */ size() { return this._arr.length; } /** * @returns {string[]} the keys that are in the queue. * @remarks Takes `O(n)` time. */ keys() { return this._arr.map(function (x) { return x.key; }); } /** * @param {Object} key - The key to check for presence in the queue. * @returns {boolean} `true` if **key** is in the queue and `false` if not. */ has(key) { return Object.prototype.hasOwnProperty.call(this._keyIndices, key); } /** * @param {Object} key - The key to get the priority for. * @returns {number | undefined} the priority for **key**. * If **key** is not present in the queue then this function returns `undefined`. * @remarks Takes `O(1)` time. */ priority(key) { var index = this._keyIndices[key]; if (index !== undefined) { return this._arr[index].priority; } } /** * @returns {string} the key for the minimum element in this queue. * @throws {Error} if the queue is empty. * @remarks Takes `O(1)` time. */ min() { if (this.size() === 0) { throw new Error('Queue underflow'); } return this._arr[0].key; } /** * Inserts a new key into the priority queue. * * @remarks Takes `O(n)` time. * * @param {Object} key the key to add. This will be coerced to a `string`. * @param {Number} priority the initial priority for the key * @returns {boolean} `true` if the key was added and `false` if it was already * present in the queue. */ add(key, priority) { var keyIndices = this._keyIndices; key = String(key); if (!Object.prototype.hasOwnProperty.call(keyIndices, key)) { var arr = this._arr; var index = arr.length; keyIndices[key] = index; arr.push({ key: key, priority: priority }); this._decrease(index); return true; } return false; } /** * Removes and returns the smallest key in the queue. * @returns {string} the key with the smallest priority * @remarks Takes `O(log n)` time. */ removeMin() { this._swap(0, this._arr.length - 1); var min = this._arr.pop(); delete this._keyIndices[min.key]; this._heapify(0); return min.key; } /** * Decreases the priority for **key** to **priority**. * * @param {Object} key the key for which to raise priority * @param {Number} priority the new priority for the key * @throws {Error} if the new priority is greater than the previous priority. */ decrease(key, priority) { var index = this._keyIndices[key]; if (priority > this._arr[index].priority) { throw new Error( 'New priority is greater than current priority. ' + 'Key: ' + key + ' Old: ' + this._arr[index].priority + ' New: ' + priority, ); } this._arr[index].priority = priority; this._decrease(index); } /** * @param {number} i - Lower index. * @private */ _heapify(i) { var arr = this._arr; var l = 2 * i; var r = l + 1; var largest = i; if (l < arr.length) { largest = arr[l].priority < arr[largest].priority ? l : largest; if (r < arr.length) { largest = arr[r].priority < arr[largest].priority ? r : largest; } if (largest !== i) { this._swap(i, largest); this._heapify(largest); } } } /** * @param {number} index - Index to decrease. * @private */ _decrease(index) { var arr = this._arr; var priority = arr[index].priority; var parent; while (index !== 0) { parent = index >> 1; if (arr[parent].priority < priority) { break; } this._swap(index, parent); index = parent; } } /** * @param {number} i - First index * @param {number} j - Second index * @private */ _swap(i, j) { var arr = this._arr; var keyIndices = this._keyIndices; var origArrI = arr[i]; var origArrJ = arr[j]; arr[i] = origArrJ; arr[j] = origArrI; keyIndices[origArrJ.key] = i; keyIndices[origArrI.key] = j; } }