priority_queue.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* Author(s):
  2. * Connor Abbott (connor@abbott.cx)
  3. *
  4. * Copyright (c) 2013 Connor Abbott
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include <ogt/priority_queue.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. priority_queue_t *priority_queue_create(compare_cb compare_gt)
  28. {
  29. priority_queue_t *queue = malloc(sizeof(priority_queue_t));
  30. if (!queue)
  31. return NULL;
  32. queue->elems = NULL;
  33. queue->num_elems = 0;
  34. queue->compare_gt = compare_gt;
  35. return queue;
  36. }
  37. void priority_queue_delete(priority_queue_t *queue)
  38. {
  39. if(queue->elems)
  40. free(queue->elems);
  41. free(queue);
  42. }
  43. unsigned priority_queue_num_elems(priority_queue_t *queue)
  44. {
  45. return queue->num_elems;
  46. }
  47. static bool is_power_of_two(unsigned num)
  48. {
  49. return !(num & (num - 1));
  50. }
  51. bool priority_queue_push(priority_queue_t *queue, void *elem)
  52. {
  53. if(queue->num_elems == 0)
  54. {
  55. queue->num_elems = 1;
  56. queue->elems = malloc(sizeof(void*));
  57. if(!queue->elems)
  58. return false;
  59. queue->elems[0] = elem;
  60. return true;
  61. }
  62. if(is_power_of_two(queue->num_elems))
  63. {
  64. queue->elems = realloc(queue->elems,
  65. queue->num_elems * 2 * sizeof(void*));
  66. if(!queue->elems)
  67. return false;
  68. }
  69. queue->elems[queue->num_elems] = elem;
  70. unsigned cur_elem = queue->num_elems;
  71. while(cur_elem != 0)
  72. {
  73. unsigned parent = (cur_elem - 1) / 2;
  74. if(!queue->compare_gt(queue->elems[cur_elem], queue->elems[parent]))
  75. break;
  76. void *temp = queue->elems[parent];
  77. queue->elems[parent] = queue->elems[cur_elem];
  78. queue->elems[cur_elem] = temp;
  79. cur_elem = parent;
  80. }
  81. queue->num_elems++;
  82. return true;
  83. }
  84. void *priority_queue_pull(priority_queue_t *queue)
  85. {
  86. if(queue->num_elems == 0)
  87. return NULL;
  88. void *ret = queue->elems[0];
  89. if(queue->num_elems == 1)
  90. {
  91. free(queue->elems);
  92. queue->elems = NULL;
  93. queue->num_elems--;
  94. return ret;
  95. }
  96. queue->elems[0] = queue->elems[queue->num_elems-1];
  97. unsigned cur_elem = 0;
  98. while (true)
  99. {
  100. unsigned smallest = cur_elem;
  101. unsigned left = 2*cur_elem + 1;
  102. unsigned right = 2*cur_elem + 2;
  103. if(left < queue->num_elems - 1 &&
  104. queue->compare_gt(queue->elems[left], queue->elems[smallest]))
  105. smallest = left;
  106. if(right < queue->num_elems - 1 &&
  107. queue->compare_gt(queue->elems[right], queue->elems[smallest]))
  108. smallest = right;
  109. if(smallest == cur_elem)
  110. break;
  111. void *temp = queue->elems[smallest];
  112. queue->elems[smallest] = queue->elems[cur_elem];
  113. queue->elems[cur_elem] = temp;
  114. cur_elem = smallest;
  115. }
  116. queue->num_elems--;
  117. if(is_power_of_two(queue->num_elems))
  118. {
  119. queue->elems = realloc(queue->elems, queue->num_elems * sizeof(void*));
  120. if(!queue->elems)
  121. return NULL;
  122. }
  123. return ret;
  124. }
  125. void *priority_queue_peek(priority_queue_t* queue)
  126. {
  127. if(queue->num_elems == 0)
  128. return NULL;
  129. return queue->elems[0];
  130. }