diff --git a/Data-Structures/Priority-Queue/PriorityQueue.js b/Data-Structures/Priority-Queue/PriorityQueue.js new file mode 100644 index 0000000000..0b283c2c7a --- /dev/null +++ b/Data-Structures/Priority-Queue/PriorityQueue.js @@ -0,0 +1,98 @@ +import MinHeap from '../heap/MinHeap'; +import Comparator from '../../utils/comparator/Comparator'; + +// It is the same as min heap except that when comparing two elements +// we take into account its priority instead of the element's value. +export default class PriorityQueue extends MinHeap { + constructor() { + // Call MinHip constructor first. + super(); + + // Setup priorities map. + this.priorities = new Map(); + + // Use custom comparator for heap elements that will take element priority + // instead of element value into account. + this.compare = new Comparator(this.comparePriority.bind(this)); + } + + /** + * Add item to the priority queue. + * @param {*} item - item we're going to add to the queue. + * @param {number} [priority] - items priority. + * @return {PriorityQueue} + */ + add(item, priority = 0) { + this.priorities.set(item, priority); + super.add(item); + return this; + } + + /** + * Remove item from priority queue. + * @param {*} item - item we're going to remove. + * @param {Comparator} [customFindingComparator] - custom function for finding the item to remove + * @return {PriorityQueue} + */ + remove(item, customFindingComparator) { + super.remove(item, customFindingComparator); + this.priorities.delete(item); + return this; + } + + /** + * Change priority of the item in a queue. + * @param {*} item - item we're going to re-prioritize. + * @param {number} priority - new item's priority. + * @return {PriorityQueue} + */ + changePriority(item, priority) { + this.remove(item, new Comparator(this.compareValue)); + this.add(item, priority); + return this; + } + + /** + * Find item by ite value. + * @param {*} item + * @return {Number[]} + */ + findByValue(item) { + return this.find(item, new Comparator(this.compareValue)); + } + + /** + * Check if item already exists in a queue. + * @param {*} item + * @return {boolean} + */ + hasValue(item) { + return this.findByValue(item).length > 0; + } + + /** + * Compares priorities of two items. + * @param {*} a + * @param {*} b + * @return {number} + */ + comparePriority(a, b) { + if (this.priorities.get(a) === this.priorities.get(b)) { + return 0; + } + return this.priorities.get(a) < this.priorities.get(b) ? -1 : 1; + } + + /** + * Compares values of two items. + * @param {*} a + * @param {*} b + * @return {number} + */ + compareValue(a, b) { + if (a === b) { + return 0; + } + return a < b ? -1 : 1; + } +}