Spaces:
Build error
Build error
import * as _ from 'lodash-es'; | |
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() { | |
this._arr = []; | |
this._keyIndices = {}; | |
} | |
/** | |
* Returns the number of elements in the queue. Takes `O(1)` time. | |
*/ | |
size() { | |
return this._arr.length; | |
} | |
/** | |
* Returns the keys that are in the queue. Takes `O(n)` time. | |
*/ | |
keys() { | |
return this._arr.map(function (x) { | |
return x.key; | |
}); | |
} | |
/** | |
* Returns `true` if **key** is in the queue and `false` if not. | |
*/ | |
has(key) { | |
return _.has(this._keyIndices, key); | |
} | |
/** | |
* Returns the priority for **key**. If **key** is not present in the queue | |
* then this function returns `undefined`. Takes `O(1)` time. | |
* | |
* @param {Object} key | |
*/ | |
priority(key) { | |
var index = this._keyIndices[key]; | |
if (index !== undefined) { | |
return this._arr[index].priority; | |
} | |
} | |
/** | |
* Returns the key for the minimum element in this queue. If the queue is | |
* empty this function throws an Error. 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. If the key already exists in | |
* the queue this function returns `false`; otherwise it will return `true`. | |
* Takes `O(n)` time. | |
* | |
* @param {Object} key the key to add | |
* @param {Number} priority the initial priority for the key | |
*/ | |
add(key, priority) { | |
var keyIndices = this._keyIndices; | |
key = String(key); | |
if (!_.has(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. 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**. If the new priority is | |
* greater than the previous priority, this function will throw an Error. | |
* | |
* @param {Object} key the key for which to raise priority | |
* @param {Number} priority the new priority for the key | |
*/ | |
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); | |
} | |
_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); | |
} | |
} | |
} | |
_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; | |
} | |
} | |
_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; | |
} | |
} | |