BHeap.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /**
  2. * @file BHeap.h
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. *
  22. * @section DESCRIPTION
  23. *
  24. * Binary heap.
  25. */
  26. #ifndef BADVPN_STRUCTURE_BHEAP_H
  27. #define BADVPN_STRUCTURE_BHEAP_H
  28. //#define BHEAP_DEBUG
  29. #include <stdint.h>
  30. #include <stddef.h>
  31. #include <misc/debug.h>
  32. /**
  33. * Handler function called by heap algorithms to compare two values.
  34. * For any two values, the comparator must always return the same result.
  35. * The <= relation defined by the comparator must be a total order.
  36. * Values are obtained like that:
  37. * - The value of a node in the heap, or a node that is being inserted is:
  38. * (uint8_t *)node + offset.
  39. * - The value being looked up is the same as given to the lookup function.
  40. *
  41. * @param user as in {@link BHeap_Init}
  42. * @param val1 first value
  43. * @param val2 second value
  44. * @return -1 if val1 < val2, 0 if val1 = val2, 1 if val1 > val2
  45. */
  46. typedef int (*BHeap_comparator) (void *user, void *val1, void *val2);
  47. struct BHeapNode;
  48. /**
  49. * Binary heap.
  50. */
  51. typedef struct {
  52. int offset;
  53. BHeap_comparator comparator;
  54. void *user;
  55. struct BHeapNode *root;
  56. struct BHeapNode *last;
  57. #ifndef NDEBUG
  58. int in_handler;
  59. #endif
  60. } BHeap;
  61. /**
  62. * Binary heap node.
  63. */
  64. typedef struct BHeapNode {
  65. struct BHeapNode *parent;
  66. struct BHeapNode *link[2];
  67. } BHeapNode;
  68. /**
  69. * Initializes the heap.
  70. *
  71. * @param o heap to initialize
  72. * @param offset offset of a value from its node
  73. * @param comparator value comparator handler function
  74. * @param user value to pass to comparator
  75. */
  76. static void BHeap_Init (BHeap *h, int offset, BHeap_comparator comparator, void *user);
  77. /**
  78. * Inserts a node into the heap.
  79. * Must not be called from comparator.
  80. *
  81. * @param o the heap
  82. * @param node uninitialized node to insert. Must have a valid value (its value
  83. * may be passed to the comparator during insertion).
  84. */
  85. static void BHeap_Insert (BHeap *h, BHeapNode *node);
  86. /**
  87. * Removes a node from the heap.
  88. * Must not be called from comparator.
  89. *
  90. * @param o the heap
  91. * @param node node to remove
  92. */
  93. static void BHeap_Remove (BHeap *h, BHeapNode *node);
  94. /**
  95. * Returns one of the smallest nodes in the heap.
  96. * Must not be called from comparator.
  97. *
  98. * @param o the heap
  99. * @return one of the smallest nodes in the heap, or NULL if there
  100. * are no nodes
  101. */
  102. static BHeapNode * BHeap_GetFirst (BHeap *h);
  103. static void * _BHeap_node_value (BHeap *o, BHeapNode *n)
  104. {
  105. return ((uint8_t *)n + o->offset);
  106. }
  107. static int _BHeap_compare_values (BHeap *o, void *v1, void *v2)
  108. {
  109. #ifndef NDEBUG
  110. o->in_handler = 1;
  111. #endif
  112. int res = o->comparator(o->user, v1, v2);
  113. #ifndef NDEBUG
  114. o->in_handler = 0;
  115. #endif
  116. ASSERT(res == -1 || res == 0 || res == 1)
  117. return res;
  118. }
  119. static int _BHeap_compare_nodes (BHeap *o, BHeapNode *n1, BHeapNode *n2)
  120. {
  121. return _BHeap_compare_values(o, _BHeap_node_value(o, n1), _BHeap_node_value(o, n2));
  122. }
  123. #ifdef BHEAP_DEBUG
  124. #define BHEAP_ASSERT(_h) _BHeap_assert(_h);
  125. #else
  126. #define BHEAP_ASSERT(_h)
  127. #endif
  128. #ifdef BHEAP_DEBUG
  129. struct _BHeap_assert_data {
  130. int state;
  131. int level;
  132. BHeapNode *prev_leaf;
  133. };
  134. #define BHEAP_ASSERT_STATE_NODEPTH 1
  135. #define BHEAP_ASSERT_STATE_LOWEST 2
  136. #define BHEAP_ASSERT_STATE_LOWESTEND 3
  137. static void _BHeap_assert_recurser (BHeap *h, BHeapNode *n, struct _BHeap_assert_data *ad, int level)
  138. {
  139. if (!n->link[0] && !n->link[1]) {
  140. if (ad->state == BHEAP_ASSERT_STATE_NODEPTH) {
  141. // leftmost none, remember depth
  142. ad->state = BHEAP_ASSERT_STATE_LOWEST;
  143. ad->level = level;
  144. }
  145. } else {
  146. // drop down
  147. if (n->link[0]) {
  148. ASSERT(_BHeap_compare_nodes(h, n, n->link[0]) <= 0)
  149. ASSERT(n->link[0]->parent == n)
  150. _BHeap_assert_recurser(h, n->link[0], ad, level + 1);
  151. }
  152. if (n->link[1]) {
  153. ASSERT(_BHeap_compare_nodes(h, n, n->link[1]) <= 0)
  154. ASSERT(n->link[1]->parent == n)
  155. _BHeap_assert_recurser(h, n->link[1], ad, level + 1);
  156. }
  157. }
  158. ASSERT(ad->state == BHEAP_ASSERT_STATE_LOWEST || ad->state == BHEAP_ASSERT_STATE_LOWESTEND)
  159. if (level < ad->level - 1) {
  160. ASSERT(n->link[0] && n->link[1])
  161. }
  162. else if (level == ad->level - 1) {
  163. switch (ad->state) {
  164. case BHEAP_ASSERT_STATE_LOWEST:
  165. if (!n->link[0]) {
  166. ad->state = BHEAP_ASSERT_STATE_LOWESTEND;
  167. ASSERT(!n->link[1])
  168. ASSERT(ad->prev_leaf == h->last)
  169. } else {
  170. if (!n->link[1]) {
  171. ad->state = BHEAP_ASSERT_STATE_LOWESTEND;
  172. ASSERT(ad->prev_leaf == h->last)
  173. }
  174. }
  175. break;
  176. case BHEAP_ASSERT_STATE_LOWESTEND:
  177. ASSERT(!n->link[0] && !n->link[1])
  178. break;
  179. }
  180. }
  181. else if (level == ad->level) {
  182. ASSERT(ad->state == BHEAP_ASSERT_STATE_LOWEST)
  183. ASSERT(!n->link[0] && !n->link[1])
  184. ad->prev_leaf = n;
  185. }
  186. else {
  187. ASSERT(0)
  188. }
  189. }
  190. static void _BHeap_assert (BHeap *h)
  191. {
  192. struct _BHeap_assert_data ad;
  193. ad.state = BHEAP_ASSERT_STATE_NODEPTH;
  194. ad.prev_leaf = NULL;
  195. if (h->root) {
  196. ASSERT(h->last)
  197. ASSERT(!h->root->parent)
  198. _BHeap_assert_recurser(h, h->root, &ad, 0);
  199. if (ad.state == BHEAP_ASSERT_STATE_LOWEST) {
  200. ASSERT(ad.prev_leaf == h->last)
  201. }
  202. } else {
  203. ASSERT(!h->last)
  204. }
  205. }
  206. #endif
  207. static void _BHeap_move_one_up (BHeap *h, BHeapNode *n)
  208. {
  209. ASSERT(n->parent)
  210. BHeapNode *p = n->parent;
  211. if (p->parent) {
  212. p->parent->link[p == p->parent->link[1]] = n;
  213. } else {
  214. h->root = n;
  215. }
  216. n->parent = p->parent;
  217. int nside = (n == p->link[1]);
  218. BHeapNode *c = p->link[!nside];
  219. p->link[0] = n->link[0];
  220. if (p->link[0]) {
  221. p->link[0]->parent = p;
  222. }
  223. p->link[1] = n->link[1];
  224. if (p->link[1]) {
  225. p->link[1]->parent = p;
  226. }
  227. n->link[nside] = p;
  228. p->parent = n;
  229. n->link[!nside] = c;
  230. if (c) {
  231. c->parent = n;
  232. }
  233. if (n == h->last) {
  234. h->last = p;
  235. }
  236. }
  237. static void _BHeap_replace_node (BHeap *h, BHeapNode *d, BHeapNode *s)
  238. {
  239. if (d->parent) {
  240. d->parent->link[d == d->parent->link[1]] = s;
  241. } else {
  242. h->root = s;
  243. }
  244. s->parent = d->parent;
  245. s->link[0] = d->link[0];
  246. if (s->link[0]) {
  247. s->link[0]->parent = s;
  248. }
  249. s->link[1] = d->link[1];
  250. if (s->link[1]) {
  251. s->link[1]->parent = s;
  252. }
  253. }
  254. void BHeap_Init (BHeap *h, int offset, BHeap_comparator comparator, void *user)
  255. {
  256. h->offset = offset;
  257. h->comparator = comparator;
  258. h->user = user;
  259. h->root = NULL;
  260. h->last = NULL;
  261. #ifndef NDEBUG
  262. h->in_handler = 0;
  263. #endif
  264. BHEAP_ASSERT(h)
  265. }
  266. void BHeap_Insert (BHeap *h, BHeapNode *node)
  267. {
  268. ASSERT(!h->in_handler)
  269. if (!h->root) {
  270. // insert to root
  271. h->root = node;
  272. h->last = node;
  273. node->parent = NULL;
  274. node->link[0] = NULL;
  275. node->link[1] = NULL;
  276. BHEAP_ASSERT(h)
  277. return;
  278. }
  279. // find the node to insert to
  280. // start with current last node and walk up left as much as possible.
  281. // That is, keep replacing the current node with the parent as long as it
  282. // exists and the current node is its right child.
  283. BHeapNode *cur = h->last;
  284. while (cur->parent && cur == cur->parent->link[1]) {
  285. cur = cur->parent;
  286. }
  287. if (cur->parent) {
  288. if (cur->parent->link[1]) {
  289. // have parent and parent has right child. Attach the new node
  290. // to the leftmost node of the parent's right subtree.
  291. cur = cur->parent->link[1];
  292. while (cur->link[0]) {
  293. cur = cur->link[0];
  294. }
  295. } else {
  296. // have parent, but parent has no right child. This can
  297. // only happen when the last node is a right child. So
  298. // attach the new node to its parent.
  299. cur = cur->parent;
  300. }
  301. } else {
  302. // have no parent, attach the new node to a new level. We're at the
  303. // root, so drop down left to obtain the node where we'll attach
  304. // the new node.
  305. while (cur->link[0]) {
  306. cur = cur->link[0];
  307. }
  308. }
  309. ASSERT((!cur->link[0] && !cur->link[1]) || (cur->link[0] && !cur->link[1]))
  310. // attach new node
  311. // the new node becomes the new last node
  312. h->last = node;
  313. cur->link[!!cur->link[0]] = node;
  314. node->parent = cur;
  315. node->link[0] = NULL;
  316. node->link[1] = NULL;
  317. // restore heap property
  318. while (node->parent && _BHeap_compare_nodes(h, node->parent, node) > 0) {
  319. _BHeap_move_one_up(h, node);
  320. }
  321. BHEAP_ASSERT(h)
  322. }
  323. void BHeap_Remove (BHeap *h, BHeapNode *node)
  324. {
  325. ASSERT(!h->in_handler)
  326. if (!node->parent && !node->link[0] && !node->link[1]) {
  327. h->root = NULL;
  328. h->last = NULL;
  329. BHEAP_ASSERT(h)
  330. return;
  331. }
  332. // locate the node before the last node
  333. BHeapNode *cur = h->last;
  334. while (cur->parent && cur == cur->parent->link[0]) {
  335. cur = cur->parent;
  336. }
  337. if (cur->parent) {
  338. ASSERT(cur->parent->link[0])
  339. cur = cur->parent->link[0];
  340. while (cur->link[1]) {
  341. cur = cur->link[1];
  342. }
  343. } else {
  344. while (cur->link[1]) {
  345. cur = cur->link[1];
  346. }
  347. }
  348. // disconnect last
  349. ASSERT(h->last->parent)
  350. h->last->parent->link[h->last == h->last->parent->link[1]] = NULL;
  351. if (node == h->last) {
  352. // deleting last; set new last
  353. h->last = cur;
  354. } else {
  355. // not deleting last; move last to node's place
  356. BHeapNode *srcnode = h->last;
  357. _BHeap_replace_node(h, node, srcnode);
  358. // set new last unless node=cur; in this case it stays the same
  359. if (node != cur) {
  360. h->last = cur;
  361. }
  362. // restore heap property
  363. if (srcnode->parent && _BHeap_compare_nodes(h, srcnode, srcnode->parent) < 0) {
  364. do {
  365. _BHeap_move_one_up(h, srcnode);
  366. } while (srcnode->parent && _BHeap_compare_nodes(h, srcnode, srcnode->parent) < 0);
  367. } else {
  368. while (srcnode->link[0] || srcnode->link[1]) {
  369. int side = (srcnode->link[1] && (_BHeap_compare_nodes(h, srcnode->link[0], srcnode->link[1]) >= 0));
  370. if (_BHeap_compare_nodes(h, srcnode, srcnode->link[side]) > 0) {
  371. _BHeap_move_one_up(h, srcnode->link[side]);
  372. } else {
  373. break;
  374. }
  375. }
  376. }
  377. }
  378. BHEAP_ASSERT(h)
  379. }
  380. BHeapNode * BHeap_GetFirst (BHeap *h)
  381. {
  382. ASSERT(!h->in_handler)
  383. return h->root;
  384. }
  385. #endif