priorityqueue.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // based off of:
  2. // https://www.geeksforgeeks.org/binary-heap/
  3. #include <iostream>
  4. #include <cstdio>
  5. #include <string>
  6. #include "priorityqueue.h"
  7. #include "json.hpp"
  8. // priority queue class using binary heap
  9. void PriorityQueue::initiateHeap(int capacity){
  10. heap_size = 0;
  11. max_size = capacity;
  12. heapArray = new int[max_size + 1];
  13. }
  14. void PriorityQueue::insert(int key){
  15. if(heap_size == max_size){
  16. std::cout << "PriorityQueue::insert called on full priority queue" << std::endl;
  17. return;
  18. }
  19. // increase array size and insert new key at end of array
  20. heap_size++;
  21. heapArray[heap_size] = key;
  22. // heapify up until the heap properties are restored
  23. heapifyUp(heap_size);
  24. }
  25. void PriorityQueue::deleteHeap(){
  26. // clean up memory so deallocate array
  27. delete[] heapArray;
  28. }
  29. void PriorityQueue::removeMax(){
  30. // check if heap is empty
  31. if (heap_size <= 0) {
  32. std::cout << "PriorityQueue::removeMax called on an empty priority queue" << std::endl;
  33. return;
  34. }
  35. if (heap_size == 1){
  36. heap_size--;
  37. } else if (heap_size == 2) { // need to check if at root to avoid error
  38. heapArray[1] = heapArray[2];
  39. heap_size--;
  40. } else {
  41. // remove the max value (at root)
  42. heapArray[1] = heapArray[heap_size];
  43. heap_size--;
  44. heapifyDown(1);
  45. }
  46. }
  47. int PriorityQueue::returnMax(){
  48. int topHeapKey = heapArray[1];
  49. return topHeapKey;
  50. }
  51. void PriorityQueue::removeKey(int key){
  52. for (int i = 1; i <= heap_size; i++) {
  53. if (heapArray[i] == key) {
  54. int beforeValue = heapArray[i];
  55. int afterValue = heapArray[heap_size];
  56. // swap the key at index with last heap key
  57. swap(&heapArray[i], &heapArray[heap_size]);
  58. // erase the last node erasing the unwanted key
  59. heap_size--;
  60. // heapify to preserve heap properties
  61. if (beforeValue == afterValue) {
  62. return;
  63. } else if (afterValue < beforeValue) {
  64. heapifyDown(i);
  65. return;
  66. } else if (afterValue > beforeValue) {
  67. heapifyUp(i);
  68. return;
  69. }
  70. }
  71. }
  72. std::cout << "PriorityQueue::removeKey key " << key << " not found" << std::endl;
  73. }
  74. void PriorityQueue::change(int key, int newKey){
  75. for (int i = 1; i <= heap_size; i++) {
  76. if (heapArray[i] == key) {
  77. heapArray[i] = newKey;
  78. // move new key value to the correct location using heapify up/down
  79. if (key == newKey) {
  80. return;
  81. } else if (newKey > key) {
  82. heapifyUp(i);
  83. return;
  84. } else if (newKey < key) {
  85. heapifyDown(i);
  86. return;
  87. }
  88. }
  89. }
  90. // if the key value could not be found, the method returns an error message
  91. std::cout << "PriorityQueue::change key " << key << " not found" << std::endl;
  92. }
  93. void PriorityQueue::swap(int *key, int *otherKey){
  94. int temp = *otherKey;
  95. *otherKey = *key;
  96. *key = temp;
  97. }
  98. void PriorityQueue::heapifyDown(int index){
  99. int lBranchIndex = 2*index;
  100. int rBranchIndex = 2*index + 1;
  101. int largerKeyIndex = index;
  102. if (lBranchIndex <= heap_size && heapArray[lBranchIndex] > heapArray[largerKeyIndex]) {
  103. largerKeyIndex = lBranchIndex;
  104. }
  105. if (rBranchIndex <= heap_size && heapArray[rBranchIndex] > heapArray[largerKeyIndex]) {
  106. largerKeyIndex = rBranchIndex;
  107. }
  108. if (largerKeyIndex != index) {
  109. swap(&heapArray[index], &heapArray[largerKeyIndex]);
  110. heapifyDown(largerKeyIndex);
  111. }
  112. }
  113. void PriorityQueue::heapifyUp(int index){
  114. if (index <= 1){
  115. return;
  116. }
  117. int curIndex = index;
  118. int parentIndex = (curIndex)/2;
  119. while (parentIndex > 0 && heapArray[parentIndex] < heapArray[curIndex]) {
  120. swap(&heapArray[parentIndex], &heapArray[curIndex]);
  121. curIndex = (curIndex)/2;
  122. parentIndex = (parentIndex)/2;
  123. }
  124. }
  125. void PriorityQueue::printJSONTree(int maxHeapSize, int numOperations){
  126. nlohmann::json outputJSON; // output JSON file
  127. for (int i = heap_size; i >= 1; i--) {
  128. int keyValue = heapArray[i]; // get the key value at array index i
  129. // find index values for the left, right, and parent nodes
  130. int lBranchIndex = 2*i;
  131. int rBranchIndex = 2*i + 1;
  132. int parentIndex = i/2;
  133. // convert index and key into strings so as to put them in JSON output
  134. std::stringstream convert2String_i;
  135. convert2String_i << i;
  136. std::string indexForJSON = convert2String_i.str();
  137. outputJSON[indexForJSON]["key"] = keyValue;
  138. // if not at the root, find the index of the parent node
  139. if (i > 1) {
  140. outputJSON[indexForJSON]["parent"] = parentIndex;
  141. }
  142. // find if there is a left branch and if so, what the index is
  143. if (lBranchIndex <= heap_size) {
  144. outputJSON[indexForJSON]["leftChild"] = lBranchIndex;
  145. }
  146. // find if there is a right branch and if so, what the index is
  147. if (rBranchIndex <= heap_size) {
  148. outputJSON[indexForJSON]["rightChild"] = rBranchIndex;
  149. }
  150. }
  151. // write out the metadata output
  152. outputJSON["metadata"]["maxHeapSize"] = maxHeapSize;
  153. outputJSON["metadata"]["max_size"] = max_size;
  154. outputJSON["metadata"]["numOperations"] = numOperations;
  155. outputJSON["metadata"]["size"] = heap_size;
  156. std::cout << outputJSON << std::endl;
  157. }