avl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // SPDX-License-Identifier: LGPL-3.0-or-later
  2. #include "../libnetdata.h"
  3. /* ------------------------------------------------------------------------- */
  4. /*
  5. * avl_insert(), avl_remove() and avl_search()
  6. * are adaptations (by Costa Tsaousis) of the AVL algorithm found in libavl
  7. * v2.0.3, so that they do not use any memory allocations and their memory
  8. * footprint is optimized (by eliminating non-necessary data members).
  9. *
  10. * libavl - library for manipulation of binary trees.
  11. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
  12. * Foundation, Inc.
  13. */
  14. /* Search |tree| for an item matching |item|, and return it if found.
  15. Otherwise return |NULL|. */
  16. avl_t *avl_search(avl_tree_type *tree, avl_t *item) {
  17. avl_t *p;
  18. // assert (tree != NULL && item != NULL);
  19. for (p = tree->root; p != NULL; ) {
  20. int cmp = tree->compar(item, p);
  21. if (cmp < 0)
  22. p = p->avl_link[0];
  23. else if (cmp > 0)
  24. p = p->avl_link[1];
  25. else /* |cmp == 0| */
  26. return p;
  27. }
  28. return NULL;
  29. }
  30. /* Inserts |item| into |tree| and returns a pointer to |item|'s address.
  31. If a duplicate item is found in the tree,
  32. returns a pointer to the duplicate without inserting |item|.
  33. */
  34. avl_t *avl_insert(avl_tree_type *tree, avl_t *item) {
  35. avl_t *y, *z; /* Top node to update balance factor, and parent. */
  36. avl_t *p, *q; /* Iterator, and parent. */
  37. avl_t *n; /* Newly inserted node. */
  38. avl_t *w; /* New root of rebalanced subtree. */
  39. unsigned char dir; /* Direction to descend. */
  40. unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
  41. int k = 0; /* Number of cached results. */
  42. // assert(tree != NULL && item != NULL);
  43. z = (avl_t *) &tree->root;
  44. y = tree->root;
  45. dir = 0;
  46. for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir]) {
  47. int cmp = tree->compar(item, p);
  48. if (cmp == 0)
  49. return p;
  50. if (p->avl_balance != 0)
  51. z = q, y = p, k = 0;
  52. da[k++] = dir = (unsigned char)(cmp > 0);
  53. }
  54. n = q->avl_link[dir] = item;
  55. // tree->avl_count++;
  56. n->avl_link[0] = n->avl_link[1] = NULL;
  57. n->avl_balance = 0;
  58. if (y == NULL) return n;
  59. for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++)
  60. if (da[k] == 0)
  61. p->avl_balance--;
  62. else
  63. p->avl_balance++;
  64. if (y->avl_balance == -2) {
  65. avl_t *x = y->avl_link[0];
  66. if (x->avl_balance == -1) {
  67. w = x;
  68. y->avl_link[0] = x->avl_link[1];
  69. x->avl_link[1] = y;
  70. x->avl_balance = y->avl_balance = 0;
  71. }
  72. else {
  73. // assert (x->avl_balance == +1);
  74. w = x->avl_link[1];
  75. x->avl_link[1] = w->avl_link[0];
  76. w->avl_link[0] = x;
  77. y->avl_link[0] = w->avl_link[1];
  78. w->avl_link[1] = y;
  79. if (w->avl_balance == -1)
  80. x->avl_balance = 0, y->avl_balance = +1;
  81. else if (w->avl_balance == 0)
  82. x->avl_balance = y->avl_balance = 0;
  83. else /* |w->avl_balance == +1| */
  84. x->avl_balance = -1, y->avl_balance = 0;
  85. w->avl_balance = 0;
  86. }
  87. }
  88. else if (y->avl_balance == +2) {
  89. avl_t *x = y->avl_link[1];
  90. if (x->avl_balance == +1) {
  91. w = x;
  92. y->avl_link[1] = x->avl_link[0];
  93. x->avl_link[0] = y;
  94. x->avl_balance = y->avl_balance = 0;
  95. }
  96. else {
  97. // assert (x->avl_balance == -1);
  98. w = x->avl_link[0];
  99. x->avl_link[0] = w->avl_link[1];
  100. w->avl_link[1] = x;
  101. y->avl_link[1] = w->avl_link[0];
  102. w->avl_link[0] = y;
  103. if (w->avl_balance == +1)
  104. x->avl_balance = 0, y->avl_balance = -1;
  105. else if (w->avl_balance == 0)
  106. x->avl_balance = y->avl_balance = 0;
  107. else /* |w->avl_balance == -1| */
  108. x->avl_balance = +1, y->avl_balance = 0;
  109. w->avl_balance = 0;
  110. }
  111. }
  112. else return n;
  113. z->avl_link[y != z->avl_link[0]] = w;
  114. // tree->avl_generation++;
  115. return n;
  116. }
  117. /* Deletes from |tree| and returns an item matching |item|.
  118. Returns a null pointer if no matching item found. */
  119. avl_t *avl_remove(avl_tree_type *tree, avl_t *item) {
  120. /* Stack of nodes. */
  121. avl_t *pa[AVL_MAX_HEIGHT]; /* Nodes. */
  122. unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
  123. int k; /* Stack pointer. */
  124. avl_t *p; /* Traverses tree to find node to delete. */
  125. int cmp; /* Result of comparison between |item| and |p|. */
  126. // assert (tree != NULL && item != NULL);
  127. k = 0;
  128. p = (avl_t *) &tree->root;
  129. for(cmp = -1; cmp != 0; cmp = tree->compar(item, p)) {
  130. unsigned char dir = (unsigned char)(cmp > 0);
  131. pa[k] = p;
  132. da[k++] = dir;
  133. p = p->avl_link[dir];
  134. if(p == NULL) return NULL;
  135. }
  136. item = p;
  137. if (p->avl_link[1] == NULL)
  138. pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
  139. else {
  140. avl_t *r = p->avl_link[1];
  141. if (r->avl_link[0] == NULL) {
  142. r->avl_link[0] = p->avl_link[0];
  143. r->avl_balance = p->avl_balance;
  144. pa[k - 1]->avl_link[da[k - 1]] = r;
  145. da[k] = 1;
  146. pa[k++] = r;
  147. }
  148. else {
  149. avl_t *s;
  150. int j = k++;
  151. for (;;) {
  152. da[k] = 0;
  153. pa[k++] = r;
  154. s = r->avl_link[0];
  155. if (s->avl_link[0] == NULL) break;
  156. r = s;
  157. }
  158. s->avl_link[0] = p->avl_link[0];
  159. r->avl_link[0] = s->avl_link[1];
  160. s->avl_link[1] = p->avl_link[1];
  161. s->avl_balance = p->avl_balance;
  162. pa[j - 1]->avl_link[da[j - 1]] = s;
  163. da[j] = 1;
  164. pa[j] = s;
  165. }
  166. }
  167. // assert (k > 0);
  168. while (--k > 0) {
  169. avl_t *y = pa[k];
  170. if (da[k] == 0) {
  171. y->avl_balance++;
  172. if (y->avl_balance == +1) break;
  173. else if (y->avl_balance == +2) {
  174. avl_t *x = y->avl_link[1];
  175. if (x->avl_balance == -1) {
  176. avl_t *w;
  177. // assert (x->avl_balance == -1);
  178. w = x->avl_link[0];
  179. x->avl_link[0] = w->avl_link[1];
  180. w->avl_link[1] = x;
  181. y->avl_link[1] = w->avl_link[0];
  182. w->avl_link[0] = y;
  183. if (w->avl_balance == +1)
  184. x->avl_balance = 0, y->avl_balance = -1;
  185. else if (w->avl_balance == 0)
  186. x->avl_balance = y->avl_balance = 0;
  187. else /* |w->avl_balance == -1| */
  188. x->avl_balance = +1, y->avl_balance = 0;
  189. w->avl_balance = 0;
  190. pa[k - 1]->avl_link[da[k - 1]] = w;
  191. }
  192. else {
  193. y->avl_link[1] = x->avl_link[0];
  194. x->avl_link[0] = y;
  195. pa[k - 1]->avl_link[da[k - 1]] = x;
  196. if (x->avl_balance == 0) {
  197. x->avl_balance = -1;
  198. y->avl_balance = +1;
  199. break;
  200. }
  201. else x->avl_balance = y->avl_balance = 0;
  202. }
  203. }
  204. }
  205. else
  206. {
  207. y->avl_balance--;
  208. if (y->avl_balance == -1) break;
  209. else if (y->avl_balance == -2) {
  210. avl_t *x = y->avl_link[0];
  211. if (x->avl_balance == +1) {
  212. avl_t *w;
  213. // assert (x->avl_balance == +1);
  214. w = x->avl_link[1];
  215. x->avl_link[1] = w->avl_link[0];
  216. w->avl_link[0] = x;
  217. y->avl_link[0] = w->avl_link[1];
  218. w->avl_link[1] = y;
  219. if (w->avl_balance == -1)
  220. x->avl_balance = 0, y->avl_balance = +1;
  221. else if (w->avl_balance == 0)
  222. x->avl_balance = y->avl_balance = 0;
  223. else /* |w->avl_balance == +1| */
  224. x->avl_balance = -1, y->avl_balance = 0;
  225. w->avl_balance = 0;
  226. pa[k - 1]->avl_link[da[k - 1]] = w;
  227. }
  228. else {
  229. y->avl_link[0] = x->avl_link[1];
  230. x->avl_link[1] = y;
  231. pa[k - 1]->avl_link[da[k - 1]] = x;
  232. if (x->avl_balance == 0) {
  233. x->avl_balance = +1;
  234. y->avl_balance = -1;
  235. break;
  236. }
  237. else x->avl_balance = y->avl_balance = 0;
  238. }
  239. }
  240. }
  241. }
  242. // tree->avl_count--;
  243. // tree->avl_generation++;
  244. return item;
  245. }
  246. /* ------------------------------------------------------------------------- */
  247. // below are functions by (C) Costa Tsaousis
  248. // ---------------------------
  249. // traversing
  250. int avl_walker(avl_t *node, int (*callback)(void * /*entry*/, void * /*data*/), void *data) {
  251. int total = 0, ret = 0;
  252. if(node->avl_link[0]) {
  253. ret = avl_walker(node->avl_link[0], callback, data);
  254. if(ret < 0) return ret;
  255. total += ret;
  256. }
  257. ret = callback(node, data);
  258. if(ret < 0) return ret;
  259. total += ret;
  260. if(node->avl_link[1]) {
  261. ret = avl_walker(node->avl_link[1], callback, data);
  262. if (ret < 0) return ret;
  263. total += ret;
  264. }
  265. return total;
  266. }
  267. int avl_traverse(avl_tree_type *tree, int (*callback)(void * /*entry*/, void * /*data*/), void *data) {
  268. if(tree->root)
  269. return avl_walker(tree->root, callback, data);
  270. else
  271. return 0;
  272. }
  273. // ---------------------------
  274. // locks
  275. static inline void avl_read_lock(avl_tree_lock *t) {
  276. #if defined(AVL_LOCK_WITH_RWLOCK)
  277. netdata_rwlock_rdlock(&t->rwlock);
  278. #else
  279. rw_spinlock_read_lock(&t->rwlock);
  280. #endif
  281. }
  282. static inline void avl_write_lock(avl_tree_lock *t) {
  283. #if defined(AVL_LOCK_WITH_RWLOCK)
  284. netdata_rwlock_wrlock(&t->rwlock);
  285. #else
  286. rw_spinlock_write_lock(&t->rwlock);
  287. #endif
  288. }
  289. static inline void avl_read_unlock(avl_tree_lock *t) {
  290. #if defined(AVL_LOCK_WITH_RWLOCK)
  291. netdata_rwlock_unlock(&t->rwlock);
  292. #else
  293. rw_spinlock_read_unlock(&t->rwlock);
  294. #endif
  295. }
  296. static inline void avl_write_unlock(avl_tree_lock *t) {
  297. #if defined(AVL_LOCK_WITH_RWLOCK)
  298. netdata_rwlock_unlock(&t->rwlock);
  299. #else
  300. rw_spinlock_write_unlock(&t->rwlock);
  301. #endif
  302. }
  303. // ---------------------------
  304. // operations with locking
  305. void avl_init_lock(avl_tree_lock *tree, int (*compar)(void * /*a*/, void * /*b*/)) {
  306. avl_init(&tree->avl_tree, compar);
  307. #if defined(AVL_LOCK_WITH_RWLOCK)
  308. if(netdata_rwlock_init(&tree->rwlock) != 0)
  309. fatal("Failed to initialize AVL rwlock");
  310. #else
  311. rw_spinlock_init(&tree->rwlock);
  312. #endif
  313. }
  314. void avl_destroy_lock(avl_tree_lock *tree __maybe_unused) {
  315. #if defined(AVL_LOCK_WITH_RWLOCK)
  316. if(netdata_rwlock_destroy(&tree->rwlock) != 0)
  317. fatal("Failed to destroy AVL rwlock");
  318. #endif
  319. }
  320. avl_t *avl_search_lock(avl_tree_lock *tree, avl_t *item) {
  321. avl_read_lock(tree);
  322. avl_t *ret = avl_search(&tree->avl_tree, item);
  323. avl_read_unlock(tree);
  324. return ret;
  325. }
  326. avl_t * avl_remove_lock(avl_tree_lock *tree, avl_t *item) {
  327. avl_write_lock(tree);
  328. avl_t *ret = avl_remove(&tree->avl_tree, item);
  329. avl_write_unlock(tree);
  330. return ret;
  331. }
  332. avl_t *avl_insert_lock(avl_tree_lock *tree, avl_t *item) {
  333. avl_write_lock(tree);
  334. avl_t * ret = avl_insert(&tree->avl_tree, item);
  335. avl_write_unlock(tree);
  336. return ret;
  337. }
  338. int avl_traverse_lock(avl_tree_lock *tree, int (*callback)(void * /*entry*/, void * /*data*/), void *data) {
  339. avl_read_lock(tree);
  340. int ret = avl_traverse(&tree->avl_tree, callback, data);
  341. avl_read_unlock(tree);
  342. return ret;
  343. }
  344. void avl_init(avl_tree_type *tree, int (*compar)(void * /*a*/, void * /*b*/)) {
  345. tree->root = NULL;
  346. tree->compar = compar;
  347. }
  348. // ------------------