heap.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #ifndef HV_HEAP_H_
  2. #define HV_HEAP_H_
  3. /*
  4. * @功能:此头文件实现了大小堆
  5. *
  6. */
  7. #include <assert.h> // for assert
  8. #include <stddef.h> // for NULL
  9. struct heap_node {
  10. struct heap_node* parent;
  11. struct heap_node* left;
  12. struct heap_node* right;
  13. };
  14. typedef int (*heap_compare_fn)(const struct heap_node* lhs, const struct heap_node* rhs);
  15. struct heap {
  16. struct heap_node* root;
  17. int nelts;
  18. // if compare is less_than, root is min of heap
  19. // if compare is larger_than, root is max of heap
  20. heap_compare_fn compare;
  21. };
  22. static inline void heap_init(struct heap* heap, heap_compare_fn fn) {
  23. heap->root = NULL;
  24. heap->nelts = 0;
  25. heap->compare = fn;
  26. }
  27. // replace s with r
  28. static inline void heap_replace(struct heap* heap, struct heap_node* s, struct heap_node* r) {
  29. // s->parent->child, s->left->parent, s->right->parent
  30. if (s->parent == NULL) heap->root = r;
  31. else if (s->parent->left == s) s->parent->left = r;
  32. else if (s->parent->right == s) s->parent->right = r;
  33. if (s->left) s->left->parent = r;
  34. if (s->right) s->right->parent = r;
  35. if (r) {
  36. //*r = *s;
  37. r->parent = s->parent;
  38. r->left = s->left;
  39. r->right = s->right;
  40. }
  41. }
  42. static inline void heap_swap(struct heap* heap, struct heap_node* parent, struct heap_node* child) {
  43. assert(child->parent == parent && (parent->left == child || parent->right == child));
  44. struct heap_node* pparent = parent->parent;
  45. struct heap_node* lchild = child->left;
  46. struct heap_node* rchild = child->right;
  47. struct heap_node* sibling = NULL;
  48. if (pparent == NULL) heap->root = child;
  49. else if (pparent->left == parent) pparent->left = child;
  50. else if (pparent->right == parent) pparent->right = child;
  51. if (lchild) lchild->parent = parent;
  52. if (rchild) rchild->parent = parent;
  53. child->parent = pparent;
  54. if (parent->left == child) {
  55. sibling = parent->right;
  56. child->left = parent;
  57. child->right = sibling;
  58. } else {
  59. sibling = parent->left;
  60. child->left = sibling;
  61. child->right = parent;
  62. }
  63. if (sibling) sibling->parent = child;
  64. parent->parent = child;
  65. parent->left = lchild;
  66. parent->right = rchild;
  67. }
  68. static inline void heap_insert(struct heap* heap, struct heap_node* node) {
  69. // get last => insert node => sift up
  70. // 0: left, 1: right
  71. int path = 0;
  72. int n,d;
  73. ++heap->nelts;
  74. // traverse from bottom to up, get path of last node
  75. for (d = 0, n = heap->nelts; n >= 2; ++d, n>>=1) {
  76. path = (path << 1) | (n & 1);
  77. }
  78. // get last->parent by path
  79. struct heap_node* parent = heap->root;
  80. while(d > 1) {
  81. parent = (path & 1) ? parent->right : parent->left;
  82. --d;
  83. path >>= 1;
  84. }
  85. // insert node
  86. node->parent = parent;
  87. if (parent == NULL) heap->root = node;
  88. else if (path & 1) parent->right = node;
  89. else parent->left = node;
  90. // sift up
  91. if (heap->compare) {
  92. while (node->parent && heap->compare(node, node->parent)) {
  93. heap_swap(heap, node->parent, node);
  94. }
  95. }
  96. }
  97. static inline void heap_remove(struct heap* heap, struct heap_node* node) {
  98. if (heap->nelts == 0) return;
  99. // get last => replace node with last => sift down and sift up
  100. // 0: left, 1: right
  101. int path = 0;
  102. int n,d;
  103. // traverse from bottom to up, get path of last node
  104. for (d = 0, n = heap->nelts; n >= 2; ++d, n>>=1) {
  105. path = (path << 1) | (n & 1);
  106. }
  107. --heap->nelts;
  108. // get last->parent by path
  109. struct heap_node* parent = heap->root;
  110. while(d > 1) {
  111. parent = (path & 1) ? parent->right : parent->left;
  112. --d;
  113. path >>= 1;
  114. }
  115. // replace node with last
  116. struct heap_node* last = NULL;
  117. if (parent == NULL) {
  118. return;
  119. }
  120. else if (path & 1) {
  121. last = parent->right;
  122. parent->right = NULL;
  123. }
  124. else {
  125. last = parent->left;
  126. parent->left = NULL;
  127. }
  128. if (last == NULL) {
  129. if (heap->root == node) {
  130. heap->root = NULL;
  131. }
  132. return;
  133. }
  134. heap_replace(heap, node, last);
  135. node->parent = node->left = node->right = NULL;
  136. if (!heap->compare) return;
  137. struct heap_node* v = last;
  138. struct heap_node* est = NULL;
  139. // sift down
  140. while (1) {
  141. est = v;
  142. if (v->left) est = heap->compare(est, v->left) ? est : v->left;
  143. if (v->right) est = heap->compare(est, v->right) ? est : v->right;
  144. if (est == v) break;
  145. heap_swap(heap, v, est);
  146. }
  147. // sift up
  148. while (v->parent && heap->compare(v, v->parent)) {
  149. heap_swap(heap, v->parent, v);
  150. }
  151. }
  152. static inline void heap_dequeue(struct heap* heap) {
  153. heap_remove(heap, heap->root);
  154. }
  155. #endif // HV_HEAP_H_