From 138c3d990521bc7a577eefdf0c24775825aa41e0 Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Tue, 3 Apr 2018 18:17:14 +0300 Subject: [PATCH] Refactor MinHeap. --- .eslintrc | 3 +- README.md | 5 +-- src/data-structures/heap/MinHeap.js | 12 +++---- .../priority-queue/PriorityQueue.js | 23 +++++++++++++ .../__test__/PriorityQueue.test.js | 34 +++++++++++++++++++ 5 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/data-structures/priority-queue/PriorityQueue.js create mode 100644 src/data-structures/priority-queue/__test__/PriorityQueue.test.js diff --git a/.eslintrc b/.eslintrc index 29137996..ac7908bd 100644 --- a/.eslintrc +++ b/.eslintrc @@ -7,6 +7,7 @@ }, "rules": { "no-bitwise": "off", - "no-lonely-if": "off" + "no-lonely-if": "off", + "class-methods-use-this": "warn" } } diff --git a/README.md b/README.md index 2e42c91e..4e651196 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,9 @@ 3. [Stack](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/stack) 4. [Hash Table](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/hash-table) 5. [Heap](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/heap) -5. [Trie](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/trie) -6. [Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree) +6. [Priority Queue](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/priority-queue) +7. [Trie](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/trie) +8. [Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree) * [Binary Search Tree](https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/tree/binary-search-tree) ## [Algorithms](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms) diff --git a/src/data-structures/heap/MinHeap.js b/src/data-structures/heap/MinHeap.js index d8e92c77..e768c0b5 100644 --- a/src/data-structures/heap/MinHeap.js +++ b/src/data-structures/heap/MinHeap.js @@ -85,7 +85,7 @@ export default class MinHeap { while ( MinHeap.hasParent(currentIndex) && - MinHeap.lessThen(this.heapContainer[currentIndex], this.parent(currentIndex)) + this.lessThen(this.heapContainer[currentIndex], this.parent(currentIndex)) ) { this.swap(currentIndex, MinHeap.getParentIndex(currentIndex)); currentIndex = MinHeap.getParentIndex(currentIndex); @@ -101,14 +101,14 @@ export default class MinHeap { while (this.hasLeftChild(currentIndex)) { if ( this.hasRightChild(currentIndex) && - MinHeap.lessThen(this.rightChild(currentIndex), this.leftChild(currentIndex)) + this.lessThen(this.rightChild(currentIndex), this.leftChild(currentIndex)) ) { nextIndex = MinHeap.getRightChildIndex(currentIndex); } else { nextIndex = MinHeap.getLeftChildIndex(currentIndex); } - if (MinHeap.lessThen(this.heapContainer[currentIndex], this.heapContainer[nextIndex])) { + if (this.lessThen(this.heapContainer[currentIndex], this.heapContainer[nextIndex])) { break; } @@ -121,7 +121,7 @@ export default class MinHeap { return this.heapContainer.toString(); } - static compare(a, b) { + compare(a, b) { if (a === b) { return 0; } @@ -129,7 +129,7 @@ export default class MinHeap { return a < b ? -1 : 1; } - static lessThen(a, b) { - return MinHeap.compare(a, b) === -1; + lessThen(a, b) { + return this.compare(a, b) === -1; } } diff --git a/src/data-structures/priority-queue/PriorityQueue.js b/src/data-structures/priority-queue/PriorityQueue.js new file mode 100644 index 00000000..c8a15706 --- /dev/null +++ b/src/data-structures/priority-queue/PriorityQueue.js @@ -0,0 +1,23 @@ +import MinHeap from '../heap/MinHeap'; + +// It is the same as min heap except that when comparing to elements +// we take into account not element's value but rather its priority. +export default class PriorityQueue extends MinHeap { + constructor() { + super(); + this.priorities = {}; + } + + add(item, priority = 0) { + this.priorities[item] = priority; + super.add(item); + } + + compare(a, b) { + if (this.priorities[a] === this.priorities[b]) { + return 0; + } + + return this.priorities[a] < this.priorities[b] ? -1 : 1; + } +} diff --git a/src/data-structures/priority-queue/__test__/PriorityQueue.test.js b/src/data-structures/priority-queue/__test__/PriorityQueue.test.js new file mode 100644 index 00000000..b628553f --- /dev/null +++ b/src/data-structures/priority-queue/__test__/PriorityQueue.test.js @@ -0,0 +1,34 @@ +import PriorityQueue from '../PriorityQueue'; + +describe('PriorityQueue', () => { + it('should create default priority queue', () => { + const priorityQueue = new PriorityQueue(); + + expect(priorityQueue).toBeDefined(); + }); + + it('should insert items to the queue and respect priorities', () => { + const priorityQueue = new PriorityQueue(); + + priorityQueue.add(10, 1); + expect(priorityQueue.peek()).toBe(10); + + priorityQueue.add(5, 2); + expect(priorityQueue.peek()).toBe(10); + + priorityQueue.add(100, 0); + expect(priorityQueue.peek()).toBe(100); + }); + + it('should poll from queue with respect to priorities', () => { + const priorityQueue = new PriorityQueue(); + + priorityQueue.add(10, 1); + priorityQueue.add(5, 2); + priorityQueue.add(100, 0); + + expect(priorityQueue.poll()).toBe(100); + expect(priorityQueue.poll()).toBe(10); + expect(priorityQueue.poll()).toBe(5); + }); +});