From 9e83d2994a88035337b6a381c9633d19f7347573 Mon Sep 17 00:00:00 2001
From: Prakash Jha <only2prakash@gmail.com>
Date: Fri, 13 Jul 2018 01:00:43 +0530
Subject: [PATCH 1/6] Min and Max PriorityQueue

Priority Queue with dynamic change priority. Array and Dictionary data types are used internally. Change Priority function works in amortized constant time, though the change in heap is in O(log n) (The supposed enhancement for previous implementation).
---
 priority_queue.js | 131 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 131 insertions(+)
 create mode 100644 priority_queue.js

diff --git a/priority_queue.js b/priority_queue.js
new file mode 100644
index 0000000..4b2d52a
--- /dev/null
+++ b/priority_queue.js
@@ -0,0 +1,131 @@
+class MinPriorityQueue {
+  constructor() {
+    this._indexLookup = {};
+    this._elementHeap = [];
+    this._priorityHeap = [];
+    this._size = 0;
+  }
+
+  comparison(value1, value2) {
+    return value1 < value2;
+  }
+
+  size() {
+    return this._size;
+  }
+
+  empty() {
+    return (this.size() === 0);
+  }
+
+  top() {
+    if (!this.empty())
+      return this._elementHeap[0];
+  }
+
+  swap(idx1, idx2) {
+    let _tempElement = this._elementHeap[idx1];
+    let _tempPriority = this._priorityHeap[idx1];
+
+    this._elementHeap[idx1] = this._elementHeap[idx2];
+    this._priorityHeap[idx1] = this._priorityHeap[idx2];
+
+    this._elementHeap[idx2] = _tempElement;
+    this._priorityHeap[idx2] = _tempPriority;
+
+    this._indexLookup[this._elementHeap[idx1]] = idx1;
+    this._indexLookup[this._elementHeap[idx2]] = idx2;
+  }
+
+  fixBottomHeap(idx) {
+    let _leftIndex = (idx << 1) + 1;
+    let _rightIndex = (idx << 1) + 2;
+
+    let _changeIndex = idx;
+    if (_leftIndex < this._size && this.comparison(this._priorityHeap[_leftIndex], this._priorityHeap[idx])) {
+      _changeIndex = _leftIndex;
+    }
+    if (_rightIndex < this._size && this.comparison(this._priorityHeap[_rightIndex], this._priorityHeap[idx])) {
+      _changeIndex = _rightIndex;
+    }
+
+    if (_changeIndex != idx) {
+      this.swap(idx, _changeIndex);
+      this.fixBottomHeap(_changeIndex);
+    }
+  }
+
+  fixTopHeap(idx) {
+    if (idx === 0) return;
+
+    let _parentIdx = (idx - 1) >> 1;
+
+    if (this.comparison(this._priorityHeap[idx], this._priorityHeap[_parentIdx])) {
+      this.swap(idx, _parentIdx);
+      this.fixTopHeap(_parentIdx);
+    }
+  }
+
+  getPriority(element) {
+    if (element in this._indexLookup) {
+      return this._priorityHeap[this._indexLookup[element]];
+    }
+  }
+
+  push(element, priority) {
+    this._indexLookup[element] = this._size;
+    this._priorityHeap.push(priority);
+    this._elementHeap.push(element);
+
+    this.fixTopHeap(this._size);
+    this._size++;
+  }
+
+  pop() {
+    if (this.empty()) return;
+    let _minPriorityElement = this._elementHeap[0];
+    this.swap(0, this._size - 1);
+    this._elementHeap.splice(-1, 1);
+    this._priorityHeap.splice(-1, 1);
+    this._size--;
+
+    this.fixBottomHeap(0);
+    return _minPriorityElement;
+  }
+
+  changePriority(item, priority) {
+    if (item in this._indexLookup === false) return;
+
+    let _index = this._indexLookup[item];
+    if (this._priorityHeap[_index] < priority) {
+      this._priorityHeap[_index] = priority;
+      this.fixBottomHeap(_index);
+    }
+    else if (this._priorityHeap[_index] > priority) {
+      this._priorityHeap[_index] = priority;
+      this.fixTopHeap(_index);
+    }
+  }
+}
+
+class MaxPriorityQueue extends MinPriorityQueue {
+  comparison(value1, value2) {
+    return value1 > value2;
+  }
+
+  changePriority(item, priority) {
+    if (item in this._indexLookup === false) return;
+
+    let _index = this._indexLookup[item];
+    if (this._priorityHeap[_index] < priority) {
+      this._priorityHeap[_index] = priority;
+      this.fixTopHeap(_index);
+    }
+    else if (this._priorityHeap[_index] > priority) {
+      this._priorityHeap[_index] = priority;
+      this.fixBottomHeap(_index);
+    }
+  }
+}
+
+module.exports = PriorityQueue;

From eab5f5b15655a4da97a715e7d1eadd8c98a460a9 Mon Sep 17 00:00:00 2001
From: forgotter <only2prakash@gmail.com>
Date: Wed, 15 Aug 2018 19:36:52 +0530
Subject: [PATCH 2/6] updated priority_queue.js

---
 priority_queue.js                     | 131 ---------------------
 src/data_structures/priority_queue.js | 159 ++++++++++++++++++++++----
 2 files changed, 136 insertions(+), 154 deletions(-)
 delete mode 100644 priority_queue.js

diff --git a/priority_queue.js b/priority_queue.js
deleted file mode 100644
index 4b2d52a..0000000
--- a/priority_queue.js
+++ /dev/null
@@ -1,131 +0,0 @@
-class MinPriorityQueue {
-  constructor() {
-    this._indexLookup = {};
-    this._elementHeap = [];
-    this._priorityHeap = [];
-    this._size = 0;
-  }
-
-  comparison(value1, value2) {
-    return value1 < value2;
-  }
-
-  size() {
-    return this._size;
-  }
-
-  empty() {
-    return (this.size() === 0);
-  }
-
-  top() {
-    if (!this.empty())
-      return this._elementHeap[0];
-  }
-
-  swap(idx1, idx2) {
-    let _tempElement = this._elementHeap[idx1];
-    let _tempPriority = this._priorityHeap[idx1];
-
-    this._elementHeap[idx1] = this._elementHeap[idx2];
-    this._priorityHeap[idx1] = this._priorityHeap[idx2];
-
-    this._elementHeap[idx2] = _tempElement;
-    this._priorityHeap[idx2] = _tempPriority;
-
-    this._indexLookup[this._elementHeap[idx1]] = idx1;
-    this._indexLookup[this._elementHeap[idx2]] = idx2;
-  }
-
-  fixBottomHeap(idx) {
-    let _leftIndex = (idx << 1) + 1;
-    let _rightIndex = (idx << 1) + 2;
-
-    let _changeIndex = idx;
-    if (_leftIndex < this._size && this.comparison(this._priorityHeap[_leftIndex], this._priorityHeap[idx])) {
-      _changeIndex = _leftIndex;
-    }
-    if (_rightIndex < this._size && this.comparison(this._priorityHeap[_rightIndex], this._priorityHeap[idx])) {
-      _changeIndex = _rightIndex;
-    }
-
-    if (_changeIndex != idx) {
-      this.swap(idx, _changeIndex);
-      this.fixBottomHeap(_changeIndex);
-    }
-  }
-
-  fixTopHeap(idx) {
-    if (idx === 0) return;
-
-    let _parentIdx = (idx - 1) >> 1;
-
-    if (this.comparison(this._priorityHeap[idx], this._priorityHeap[_parentIdx])) {
-      this.swap(idx, _parentIdx);
-      this.fixTopHeap(_parentIdx);
-    }
-  }
-
-  getPriority(element) {
-    if (element in this._indexLookup) {
-      return this._priorityHeap[this._indexLookup[element]];
-    }
-  }
-
-  push(element, priority) {
-    this._indexLookup[element] = this._size;
-    this._priorityHeap.push(priority);
-    this._elementHeap.push(element);
-
-    this.fixTopHeap(this._size);
-    this._size++;
-  }
-
-  pop() {
-    if (this.empty()) return;
-    let _minPriorityElement = this._elementHeap[0];
-    this.swap(0, this._size - 1);
-    this._elementHeap.splice(-1, 1);
-    this._priorityHeap.splice(-1, 1);
-    this._size--;
-
-    this.fixBottomHeap(0);
-    return _minPriorityElement;
-  }
-
-  changePriority(item, priority) {
-    if (item in this._indexLookup === false) return;
-
-    let _index = this._indexLookup[item];
-    if (this._priorityHeap[_index] < priority) {
-      this._priorityHeap[_index] = priority;
-      this.fixBottomHeap(_index);
-    }
-    else if (this._priorityHeap[_index] > priority) {
-      this._priorityHeap[_index] = priority;
-      this.fixTopHeap(_index);
-    }
-  }
-}
-
-class MaxPriorityQueue extends MinPriorityQueue {
-  comparison(value1, value2) {
-    return value1 > value2;
-  }
-
-  changePriority(item, priority) {
-    if (item in this._indexLookup === false) return;
-
-    let _index = this._indexLookup[item];
-    if (this._priorityHeap[_index] < priority) {
-      this._priorityHeap[_index] = priority;
-      this.fixTopHeap(_index);
-    }
-    else if (this._priorityHeap[_index] > priority) {
-      this._priorityHeap[_index] = priority;
-      this.fixBottomHeap(_index);
-    }
-  }
-}
-
-module.exports = PriorityQueue;
diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js
index afd3225..3cffbf6 100644
--- a/src/data_structures/priority_queue.js
+++ b/src/data_structures/priority_queue.js
@@ -1,15 +1,20 @@
-const MinHeap = require('./heap').MinHeap;
-
-/**
- * Extends the MinHeap with the only difference that
- * the heap operations are performed based on the priority of the element
- * and not on the element itself
- */
-class PriorityQueue extends MinHeap {
-  constructor(initialItems) {
-    super((a, b) => (this.priority(a) < this.priority(b) ? -1 : 1));
+/*
+Minimum Priority Queue implementation using heap.
+
+elementHeap stores all element,
+priorityHeap stores priority for given element,
+priority[i] stores priority of element[i].
 
-    this._priority = {};
+indexLookup stores index of element, so when priority is changed,
+the top or bottom heap can be fixed from that position itself.
+*/
+
+class PriorityQueue {
+  constructor(initialItems) {
+    this._indexLookup = {};
+    this._elementHeap = [];
+    this._priorityHeap = [];
+    this._size = 0;
 
     initialItems = initialItems || {};
     Object.keys(initialItems).forEach(item => {
@@ -17,28 +22,136 @@ class PriorityQueue extends MinHeap {
     });
   }
 
+  // comparator function
+  comparison(value1, value2) {
+    return value1 < value2;
+  }
+
+  // Returns true if heap is empty
+  isEmpty() {
+    return (this._size === 0);
+  }
+
+  // swaps element with their priorities and their indexLookup values
+  _swap(idx1, idx2) {
+    let _tempElement = this._elementHeap[idx1];
+    let _tempPriority = this._priorityHeap[idx1];
+
+    this._elementHeap[idx1] = this._elementHeap[idx2];
+    this._priorityHeap[idx1] = this._priorityHeap[idx2];
+
+    this._elementHeap[idx2] = _tempElement;
+    this._priorityHeap[idx2] = _tempPriority;
+
+    this._indexLookup[this._elementHeap[idx1]] = idx1;
+    this._indexLookup[this._elementHeap[idx2]] = idx2;
+  }
+
+  /*
+  To fix bootom heap from position: idx
+
+  Finds if left or right child is smaller, if true, swaps smallest element
+  with parent and then calls fixBottomHeap for index of smallest element
+  */
+  _fixBottomHeap(idx) {
+    let _leftIndex = (idx << 1) + 1;
+    let _rightIndex = (idx << 1) + 2;
+
+    let _changeIndex = idx;
+    if (_leftIndex < this._size &&
+      this.comparison(
+        this._priorityHeap[_leftIndex], this._priorityHeap[_changeIndex])) {
+      _changeIndex = _leftIndex;
+    }
+    if (_rightIndex < this._size &&
+      this.comparison(
+        this._priorityHeap[_rightIndex], this._priorityHeap[_changeIndex])) {
+      _changeIndex = _rightIndex;
+    }
+
+    if (_changeIndex != idx) {
+      this._swap(idx, _changeIndex);
+      this._fixBottomHeap(_changeIndex);
+    }
+  }
+
+  /*
+  Fix the top heap from position: idx
+
+  Finds if the element at given index is smaller than parent, if true
+  swaps it and call fixTopHeap for its parent
+  */
+  _fixTopHeap(idx) {
+    if (idx === 0) return;
+
+    let _parentIdx = (idx - 1) >> 1;
+
+    if (this.comparison(
+      this._priorityHeap[idx], this._priorityHeap[_parentIdx])) {
+      this._swap(idx, _parentIdx);
+      this._fixTopHeap(_parentIdx);
+    }
+  }
+
+  /*
+  Returns priority of element
+  */
+  priority(element) {
+    if (element in this._indexLookup) {
+      return this._priorityHeap[this._indexLookup[element]];
+    }
+  }
+
+  /*
+  Insert item with its priority in heap
+  */
   insert(item, priority) {
-    if (this._priority[item] !== undefined) {
+    if (item == null) return;
+    if (item in this._indexLookup) {
       return this.changePriority(item, priority);
     }
-    this._priority[item] = priority;
-    super.insert(item);
+
+    this._indexLookup[item] = this._size;
+    this._priorityHeap.push(priority);
+    this._elementHeap.push(item);
+
+    this._fixTopHeap(this._size);
+    this._size++;
   }
 
+  /*
+  Returns item with least priority from heap and removes it from heap
+  */
   extract(withPriority) {
-    const min = MinHeap.prototype.extract.call(this);
-    return withPriority
-      ? min && {item: min, priority: this._priority[min]}
-      : min;
-  }
+    if (this.isEmpty()) return;
+    let _minPriorityItem = this._elementHeap[0];
+    let _minPriority = this._priorityHeap[0];
+    this._swap(0, this._size - 1);
+    this._elementHeap.splice(-1, 1);
+    this._priorityHeap.splice(-1, 1);
+    this._indexLookup[_minPriorityItem] = null;
+    this._size--;
 
-  priority(item) {
-    return this._priority[item];
+    this._fixBottomHeap(0);
+    return withPriority
+    ? _minPriorityItem && {item: _minPriorityItem, priority: _minPriority}
+    : _minPriorityItem;
   }
 
+  /*
+  To change priority of element already in heap
+  */
   changePriority(item, priority) {
-    this._priority[item] = priority;
-    this.heapify();
+    if (item in this._indexLookup === false) return;
+
+    let _index = this._indexLookup[item];
+    if (this._priorityHeap[_index] < priority) {
+      this._priorityHeap[_index] = priority;
+      this._fixBottomHeap(_index);
+    } else if (this._priorityHeap[_index] > priority) {
+      this._priorityHeap[_index] = priority;
+      this._fixTopHeap(_index);
+    }
   }
 }
 

From ea03c389aec3b1fdef3a62edf0242abcab947d50 Mon Sep 17 00:00:00 2001
From: Prakash Jha <only2prakash@gmail.com>
Date: Thu, 16 Aug 2018 13:14:07 +0530
Subject: [PATCH 3/6] Refactored fixBottomHeap method

---
 src/data_structures/priority_queue.js | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js
index 3cffbf6..b98ec57 100644
--- a/src/data_structures/priority_queue.js
+++ b/src/data_structures/priority_queue.js
@@ -54,24 +54,19 @@ class PriorityQueue {
   with parent and then calls fixBottomHeap for index of smallest element
   */
   _fixBottomHeap(idx) {
-    let _leftIndex = (idx << 1) + 1;
-    let _rightIndex = (idx << 1) + 2;
-
-    let _changeIndex = idx;
-    if (_leftIndex < this._size &&
-      this.comparison(
-        this._priorityHeap[_leftIndex], this._priorityHeap[_changeIndex])) {
-      _changeIndex = _leftIndex;
-    }
-    if (_rightIndex < this._size &&
-      this.comparison(
-        this._priorityHeap[_rightIndex], this._priorityHeap[_changeIndex])) {
-      _changeIndex = _rightIndex;
+    let changeIdx = idx;
+    let childIdx = (idx << 1) + 1;
+    while (childIdx <= (idx << 1) + 2) {
+      if (childIdx < this._size && this.comparison(
+        this._priorityHeap[childIdx], this._priorityHeap[changeIdx])) {
+        changeIdx = childIdx;
+      }
+      childIdx++;
     }
 
-    if (_changeIndex != idx) {
-      this._swap(idx, _changeIndex);
-      this._fixBottomHeap(_changeIndex);
+    if (changeIdx != idx) {
+      this._swap(idx, changeIdx);
+      this._fixBottomHeap(changeIdx);
     }
   }
 

From d168bf0ab9c5d3384aafb3df64fd2a7ff4ee055c Mon Sep 17 00:00:00 2001
From: Prakash Jha <only2prakash@gmail.com>
Date: Thu, 16 Aug 2018 13:18:26 +0530
Subject: [PATCH 4/6] Reducing Cognitive code complexity

---
 src/data_structures/priority_queue.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js
index b98ec57..8232ee9 100644
--- a/src/data_structures/priority_queue.js
+++ b/src/data_structures/priority_queue.js
@@ -55,8 +55,9 @@ class PriorityQueue {
   */
   _fixBottomHeap(idx) {
     let changeIdx = idx;
-    let childIdx = (idx << 1) + 1;
-    while (childIdx <= (idx << 1) + 2) {
+    let childIdx = idx * 2 + 1;
+    let rightChildIdx = idx * 2 + 2;
+    while (childIdx <= rightChildIdx) {
       if (childIdx < this._size && this.comparison(
         this._priorityHeap[childIdx], this._priorityHeap[changeIdx])) {
         changeIdx = childIdx;

From f244049a2da3682b51bb0308d1e0745b20243719 Mon Sep 17 00:00:00 2001
From: Prakash Jha <only2prakash@gmail.com>
Date: Tue, 21 Aug 2018 10:55:17 +0530
Subject: [PATCH 5/6] Reducing code complexity

---
 src/data_structures/priority_queue.js | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js
index 8232ee9..92001b0 100644
--- a/src/data_structures/priority_queue.js
+++ b/src/data_structures/priority_queue.js
@@ -55,14 +55,12 @@ class PriorityQueue {
   */
   _fixBottomHeap(idx) {
     let changeIdx = idx;
-    let childIdx = idx * 2 + 1;
-    let rightChildIdx = idx * 2 + 2;
-    while (childIdx <= rightChildIdx) {
-      if (childIdx < this._size && this.comparison(
+    let maxChildIdx = Math.min(idx*2 + 2, this._size - 1);
+    for (let childIdx = idx*2 + 1; childIdx <= maxChildIdx; childIdx++) {
+      if (this.comparison(
         this._priorityHeap[childIdx], this._priorityHeap[changeIdx])) {
         changeIdx = childIdx;
       }
-      childIdx++;
     }
 
     if (changeIdx != idx) {

From 2bf4a043b97c6a97df5d79500b30a3a73e7fc5d3 Mon Sep 17 00:00:00 2001
From: Prakash Jha <only2prakash@gmail.com>
Date: Wed, 22 Aug 2018 15:11:26 +0530
Subject: [PATCH 6/6] fixed comments and bug

fixed some variable naming in comments.
In extract(), now the removed element will be deleted from indexLookup and not set to null.
---
 src/data_structures/priority_queue.js | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/data_structures/priority_queue.js b/src/data_structures/priority_queue.js
index 92001b0..f87c283 100644
--- a/src/data_structures/priority_queue.js
+++ b/src/data_structures/priority_queue.js
@@ -3,8 +3,7 @@ Minimum Priority Queue implementation using heap.
 
 elementHeap stores all element,
 priorityHeap stores priority for given element,
-priority[i] stores priority of element[i].
-
+priorityHeap[i] stores priority of elementHeap[i].
 indexLookup stores index of element, so when priority is changed,
 the top or bottom heap can be fixed from that position itself.
 */
@@ -48,7 +47,7 @@ class PriorityQueue {
   }
 
   /*
-  To fix bootom heap from position: idx
+  To fix bottom heap from position: idx
 
   Finds if left or right child is smaller, if true, swaps smallest element
   with parent and then calls fixBottomHeap for index of smallest element
@@ -123,7 +122,7 @@ class PriorityQueue {
     this._swap(0, this._size - 1);
     this._elementHeap.splice(-1, 1);
     this._priorityHeap.splice(-1, 1);
-    this._indexLookup[_minPriorityItem] = null;
+    delete this._indexLookup[_minPriorityItem];
     this._size--;
 
     this._fixBottomHeap(0);