avl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  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. void avl_read_lock(avl_tree_lock *t) {
  276. #ifndef AVL_WITHOUT_PTHREADS
  277. #ifdef AVL_LOCK_WITH_MUTEX
  278. netdata_mutex_lock(&t->mutex);
  279. #else
  280. netdata_rwlock_rdlock(&t->rwlock);
  281. #endif
  282. #endif /* AVL_WITHOUT_PTHREADS */
  283. }
  284. void avl_write_lock(avl_tree_lock *t) {
  285. #ifndef AVL_WITHOUT_PTHREADS
  286. #ifdef AVL_LOCK_WITH_MUTEX
  287. netdata_mutex_lock(&t->mutex);
  288. #else
  289. netdata_rwlock_wrlock(&t->rwlock);
  290. #endif
  291. #endif /* AVL_WITHOUT_PTHREADS */
  292. }
  293. void avl_unlock(avl_tree_lock *t) {
  294. #ifndef AVL_WITHOUT_PTHREADS
  295. #ifdef AVL_LOCK_WITH_MUTEX
  296. netdata_mutex_unlock(&t->mutex);
  297. #else
  298. netdata_rwlock_unlock(&t->rwlock);
  299. #endif
  300. #endif /* AVL_WITHOUT_PTHREADS */
  301. }
  302. // ---------------------------
  303. // operations with locking
  304. void avl_init_lock(avl_tree_lock *tree, int (*compar)(void * /*a*/, void * /*b*/)) {
  305. avl_init(&tree->avl_tree, compar);
  306. #ifndef AVL_WITHOUT_PTHREADS
  307. int lock;
  308. #ifdef AVL_LOCK_WITH_MUTEX
  309. lock = netdata_mutex_init(&tree->mutex, NULL);
  310. #else
  311. lock = netdata_rwlock_init(&tree->rwlock);
  312. #endif
  313. if(lock != 0)
  314. fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
  315. #endif /* AVL_WITHOUT_PTHREADS */
  316. }
  317. void avl_destroy_lock(avl_tree_lock *tree) {
  318. #ifndef AVL_WITHOUT_PTHREADS
  319. int lock;
  320. #ifdef AVL_LOCK_WITH_MUTEX
  321. lock = pthread_mutex_destroy(&tree->mutex);
  322. #else
  323. lock = pthread_rwlock_destroy(&tree->rwlock);
  324. #endif
  325. if(lock != 0)
  326. fatal("Failed to destroy AVL mutex/rwlock, error: %d", lock);
  327. #endif /* AVL_WITHOUT_PTHREADS */
  328. }
  329. avl_t *avl_search_lock(avl_tree_lock *tree, avl_t *item) {
  330. avl_read_lock(tree);
  331. avl_t *ret = avl_search(&tree->avl_tree, item);
  332. avl_unlock(tree);
  333. return ret;
  334. }
  335. avl_t * avl_remove_lock(avl_tree_lock *tree, avl_t *item) {
  336. avl_write_lock(tree);
  337. avl_t *ret = avl_remove(&tree->avl_tree, item);
  338. avl_unlock(tree);
  339. return ret;
  340. }
  341. avl_t *avl_insert_lock(avl_tree_lock *tree, avl_t *item) {
  342. avl_write_lock(tree);
  343. avl_t * ret = avl_insert(&tree->avl_tree, item);
  344. avl_unlock(tree);
  345. return ret;
  346. }
  347. int avl_traverse_lock(avl_tree_lock *tree, int (*callback)(void * /*entry*/, void * /*data*/), void *data) {
  348. int ret;
  349. avl_read_lock(tree);
  350. ret = avl_traverse(&tree->avl_tree, callback, data);
  351. avl_unlock(tree);
  352. return ret;
  353. }
  354. void avl_init(avl_tree_type *tree, int (*compar)(void * /*a*/, void * /*b*/)) {
  355. tree->root = NULL;
  356. tree->compar = compar;
  357. }
  358. // ------------------