/data/heap.d

http://github.com/wilkie/djehuty · D · 207 lines · 137 code · 44 blank · 26 comment · 25 complexity · 5e01117bb41059768e0c020879318c3a MD5 · raw file

  1. /*
  2. * priorityqueue.d
  3. *
  4. * A simple implementation of a priority queue (a min-heap or a max-heap).
  5. * References are stored with an array indexed at 1. Implementation is a sorted heap.
  6. *
  7. * Author: Dave Wilkinson
  8. * Originated: November 7th, 2009
  9. *
  10. */
  11. module data.heap;
  12. import data.list;
  13. import core.util;
  14. enum : bool {
  15. MinHeap = true,
  16. MaxHeap = false
  17. }
  18. interface HeapInterface(T, bool minHeap = MinHeap) {
  19. template add(R) {
  20. void add(R item);
  21. }
  22. T remove();
  23. void clear();
  24. bool empty();
  25. size_t length();
  26. }
  27. class PriorityQueue(T, bool minHeap = MinHeap) : HeapInterface!(T, minHeap) {
  28. this() {
  29. _length = 0;
  30. }
  31. template add(R) {
  32. void add(R item) {
  33. // determine location for data:
  34. size_t idx = _length + 1;
  35. // check for bounds
  36. while (idx >= _data.length) {
  37. _resize();
  38. }
  39. // add data:
  40. static if (IsArray!(R)) {
  41. _data[idx] = item.dup;
  42. }
  43. else {
  44. _data[idx] = cast(T)item;
  45. }
  46. _length++;
  47. // bubble data up:
  48. _bubbleUp(idx);
  49. }
  50. }
  51. T remove() {
  52. T ret;
  53. if (empty()) {
  54. // XXX: Throw Tree Exception
  55. return ret;
  56. }
  57. ret = _data[1];
  58. // take last item, place at root:
  59. _data[1] = _data[_length];
  60. _length--;
  61. // bubble data down:
  62. _bubbleDown(1);
  63. // return saved temp
  64. return ret;
  65. }
  66. T peek() {
  67. T ret;
  68. if (empty()) {
  69. // XXX: Throw Tree Exception
  70. return ret;
  71. }
  72. return _data[1];
  73. }
  74. bool empty() {
  75. return _length == 0;
  76. }
  77. void clear() {
  78. _length = 0;
  79. _data = null;
  80. }
  81. size_t length() {
  82. return _length;
  83. }
  84. protected:
  85. void _bubbleUp(size_t idx) {
  86. if (idx <= 1) {
  87. // base case
  88. return;
  89. }
  90. // get the parent, note the array is indexed at 1
  91. size_t parent = idx >> 1;
  92. // compare
  93. static if (minHeap) {
  94. if (_data[parent] > _data[idx]) {
  95. _swap(parent, idx);
  96. _bubbleUp(parent);
  97. }
  98. }
  99. else {
  100. if (_data[parent] < _data[idx]) {
  101. _swap(parent, idx);
  102. _bubbleUp(parent);
  103. }
  104. }
  105. }
  106. void _bubbleDown(size_t idx) {
  107. if (idx >= _length + 1) {
  108. // base case
  109. return;
  110. }
  111. size_t idx1, idx2, bestIdx;
  112. idx1 = idx << 1;
  113. idx2 = idx1 + 1;
  114. if (idx1 >= _length + 1) {
  115. // base case
  116. return;
  117. }
  118. // compare idx1 and idx2
  119. bestIdx = idx1;
  120. if (idx2 <= _length) {
  121. static if (minHeap) {
  122. if (_data[idx1] > _data[idx2]) {
  123. bestIdx = idx2;
  124. }
  125. }
  126. else {
  127. if (_data[idx1] < _data[idx2]) {
  128. bestIdx = idx2;
  129. }
  130. }
  131. }
  132. // compare idx and bestIdx
  133. static if (minHeap) {
  134. if (_data[bestIdx] < _data[idx]) {
  135. _swap(bestIdx, idx);
  136. _bubbleDown(bestIdx);
  137. }
  138. }
  139. else {
  140. if (_data[bestIdx] > _data[idx]) {
  141. _swap(bestIdx, idx);
  142. _bubbleDown(bestIdx);
  143. }
  144. }
  145. }
  146. void _swap(size_t idx1, size_t idx2) {
  147. T tmp = _data[idx1];
  148. _data[idx1] = _data[idx2];
  149. _data[idx2] = tmp;
  150. }
  151. void _resize() {
  152. T[] temp = _data;
  153. if (_data.length == 0) {
  154. _data = new T[10];
  155. }
  156. else {
  157. _data = new T[_data.length * 2];
  158. }
  159. _data[0..temp.length] = temp[0..$];
  160. }
  161. size_t _length;
  162. T[] _data;
  163. }