gl_anytree_oset.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /* Ordered set data type implemented by a binary tree.
  2. Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc.
  3. Written by Bruno Haible <bruno@clisp.org>, 2006.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  14. /* Common code of gl_avltree_oset.c and gl_rbtree_oset.c. */
  15. /* An item on the stack used for iterating across the elements. */
  16. typedef struct
  17. {
  18. gl_oset_node_t node;
  19. bool rightp;
  20. } iterstack_item_t;
  21. /* A stack used for iterating across the elements. */
  22. typedef iterstack_item_t iterstack_t[MAXHEIGHT];
  23. static gl_oset_t
  24. gl_tree_nx_create_empty (gl_oset_implementation_t implementation,
  25. gl_setelement_compar_fn compar_fn,
  26. gl_setelement_dispose_fn dispose_fn)
  27. {
  28. struct gl_oset_impl *set =
  29. (struct gl_oset_impl *) malloc (sizeof (struct gl_oset_impl));
  30. if (set == NULL)
  31. return NULL;
  32. set->base.vtable = implementation;
  33. set->base.compar_fn = compar_fn;
  34. set->base.dispose_fn = dispose_fn;
  35. set->root = NULL;
  36. set->count = 0;
  37. return set;
  38. }
  39. static size_t _GL_ATTRIBUTE_PURE
  40. gl_tree_size (gl_oset_t set)
  41. {
  42. return set->count;
  43. }
  44. /* Returns the next node in the tree, or NULL if there is none. */
  45. static inline gl_oset_node_t _GL_ATTRIBUTE_PURE
  46. gl_tree_next_node (gl_oset_node_t node)
  47. {
  48. if (node->right != NULL)
  49. {
  50. node = node->right;
  51. while (node->left != NULL)
  52. node = node->left;
  53. }
  54. else
  55. {
  56. while (node->parent != NULL && node->parent->right == node)
  57. node = node->parent;
  58. node = node->parent;
  59. }
  60. return node;
  61. }
  62. /* Returns the previous node in the tree, or NULL if there is none. */
  63. static inline gl_oset_node_t _GL_ATTRIBUTE_PURE
  64. gl_tree_prev_node (gl_oset_node_t node)
  65. {
  66. if (node->left != NULL)
  67. {
  68. node = node->left;
  69. while (node->right != NULL)
  70. node = node->right;
  71. }
  72. else
  73. {
  74. while (node->parent != NULL && node->parent->left == node)
  75. node = node->parent;
  76. node = node->parent;
  77. }
  78. return node;
  79. }
  80. static bool
  81. gl_tree_search (gl_oset_t set, const void *elt)
  82. {
  83. gl_setelement_compar_fn compar = set->base.compar_fn;
  84. gl_oset_node_t node;
  85. for (node = set->root; node != NULL; )
  86. {
  87. int cmp = (compar != NULL
  88. ? compar (node->value, elt)
  89. : (node->value > elt ? 1 :
  90. node->value < elt ? -1 : 0));
  91. if (cmp < 0)
  92. node = node->right;
  93. else if (cmp > 0)
  94. node = node->left;
  95. else /* cmp == 0 */
  96. /* We have an element equal to ELT. */
  97. return true;
  98. }
  99. return false;
  100. }
  101. static bool
  102. gl_tree_search_atleast (gl_oset_t set,
  103. gl_setelement_threshold_fn threshold_fn,
  104. const void *threshold,
  105. const void **eltp)
  106. {
  107. gl_oset_node_t node;
  108. for (node = set->root; node != NULL; )
  109. {
  110. if (! threshold_fn (node->value, threshold))
  111. node = node->right;
  112. else
  113. {
  114. /* We have an element >= THRESHOLD. But we need the leftmost such
  115. element. */
  116. gl_oset_node_t found = node;
  117. node = node->left;
  118. for (; node != NULL; )
  119. {
  120. if (! threshold_fn (node->value, threshold))
  121. node = node->right;
  122. else
  123. {
  124. found = node;
  125. node = node->left;
  126. }
  127. }
  128. *eltp = found->value;
  129. return true;
  130. }
  131. }
  132. return false;
  133. }
  134. static gl_oset_node_t
  135. gl_tree_search_node (gl_oset_t set, const void *elt)
  136. {
  137. gl_setelement_compar_fn compar = set->base.compar_fn;
  138. gl_oset_node_t node;
  139. for (node = set->root; node != NULL; )
  140. {
  141. int cmp = (compar != NULL
  142. ? compar (node->value, elt)
  143. : (node->value > elt ? 1 :
  144. node->value < elt ? -1 : 0));
  145. if (cmp < 0)
  146. node = node->right;
  147. else if (cmp > 0)
  148. node = node->left;
  149. else /* cmp == 0 */
  150. /* We have an element equal to ELT. */
  151. return node;
  152. }
  153. return NULL;
  154. }
  155. static int
  156. gl_tree_nx_add (gl_oset_t set, const void *elt)
  157. {
  158. gl_setelement_compar_fn compar;
  159. gl_oset_node_t node = set->root;
  160. if (node == NULL)
  161. {
  162. if (gl_tree_nx_add_first (set, elt) == NULL)
  163. return -1;
  164. return true;
  165. }
  166. compar = set->base.compar_fn;
  167. for (;;)
  168. {
  169. int cmp = (compar != NULL
  170. ? compar (node->value, elt)
  171. : (node->value > elt ? 1 :
  172. node->value < elt ? -1 : 0));
  173. if (cmp < 0)
  174. {
  175. if (node->right == NULL)
  176. {
  177. if (gl_tree_nx_add_after (set, node, elt) == NULL)
  178. return -1;
  179. return true;
  180. }
  181. node = node->right;
  182. }
  183. else if (cmp > 0)
  184. {
  185. if (node->left == NULL)
  186. {
  187. if (gl_tree_nx_add_before (set, node, elt) == NULL)
  188. return -1;
  189. return true;
  190. }
  191. node = node->left;
  192. }
  193. else /* cmp == 0 */
  194. return false;
  195. }
  196. }
  197. static bool
  198. gl_tree_remove (gl_oset_t set, const void *elt)
  199. {
  200. gl_oset_node_t node = gl_tree_search_node (set, elt);
  201. if (node != NULL)
  202. return gl_tree_remove_node (set, node);
  203. else
  204. return false;
  205. }
  206. static int
  207. gl_tree_update (gl_oset_t set, const void *elt,
  208. void (*action) (const void * /*elt*/, void * /*action_data*/),
  209. void *action_data)
  210. {
  211. /* Like gl_tree_remove, action (...), gl_tree_nx_add, except that we don't
  212. actually remove ELT. */
  213. /* Remember the old node. Don't free it. */
  214. gl_oset_node_t old_node = gl_tree_search_node (set, elt);
  215. /* Invoke ACTION. */
  216. action (elt, action_data);
  217. /* Determine where to put the node now. */
  218. if (old_node != NULL)
  219. {
  220. if (set->count > 1)
  221. {
  222. gl_setelement_compar_fn compar = set->base.compar_fn;
  223. gl_oset_node_t prev_node = gl_tree_prev_node (old_node);
  224. gl_oset_node_t next_node = gl_tree_next_node (old_node);
  225. if (!(compar != NULL
  226. ? (prev_node == NULL || compar (prev_node->value, elt) < 0)
  227. && (next_node == NULL || compar (next_node->value, elt) > 0)
  228. : (prev_node == NULL || prev_node->value < elt)
  229. && (next_node == NULL || next_node->value > elt)))
  230. {
  231. /* old_node needs to move in the tree. */
  232. gl_oset_node_t node;
  233. /* Remove the node from the tree. Don't free it. */
  234. gl_tree_remove_node_no_free (set, old_node);
  235. node = set->root;
  236. for (;;)
  237. {
  238. int cmp = (compar != NULL
  239. ? compar (node->value, elt)
  240. : (node->value > elt ? 1 :
  241. node->value < elt ? -1 : 0));
  242. if (cmp < 0)
  243. {
  244. if (node->right == NULL)
  245. {
  246. gl_tree_add_node_after (set, node, old_node);
  247. return true;
  248. }
  249. node = node->right;
  250. }
  251. else if (cmp > 0)
  252. {
  253. if (node->left == NULL)
  254. {
  255. gl_tree_add_node_before (set, node, old_node);
  256. return true;
  257. }
  258. node = node->left;
  259. }
  260. else /* cmp == 0 */
  261. {
  262. /* Two elements are the same. */
  263. NODE_PAYLOAD_DISPOSE (set, old_node)
  264. free (old_node);
  265. return -1;
  266. }
  267. }
  268. }
  269. }
  270. }
  271. return 0;
  272. }
  273. static void
  274. gl_tree_oset_free (gl_oset_t set)
  275. {
  276. /* Iterate across all elements in post-order. */
  277. gl_oset_node_t node = set->root;
  278. iterstack_t stack;
  279. iterstack_item_t *stack_ptr = &stack[0];
  280. for (;;)
  281. {
  282. /* Descend on left branch. */
  283. for (;;)
  284. {
  285. if (node == NULL)
  286. break;
  287. stack_ptr->node = node;
  288. stack_ptr->rightp = false;
  289. node = node->left;
  290. stack_ptr++;
  291. }
  292. /* Climb up again. */
  293. for (;;)
  294. {
  295. if (stack_ptr == &stack[0])
  296. goto done_iterate;
  297. stack_ptr--;
  298. node = stack_ptr->node;
  299. if (!stack_ptr->rightp)
  300. break;
  301. /* Free the current node. */
  302. if (set->base.dispose_fn != NULL)
  303. set->base.dispose_fn (node->value);
  304. free (node);
  305. }
  306. /* Descend on right branch. */
  307. stack_ptr->rightp = true;
  308. node = node->right;
  309. stack_ptr++;
  310. }
  311. done_iterate:
  312. free (set);
  313. }
  314. /* --------------------- gl_oset_iterator_t Data Type --------------------- */
  315. static gl_oset_iterator_t _GL_ATTRIBUTE_PURE
  316. gl_tree_iterator (gl_oset_t set)
  317. {
  318. gl_oset_iterator_t result;
  319. gl_oset_node_t node;
  320. result.vtable = set->base.vtable;
  321. result.set = set;
  322. /* Start node is the leftmost node. */
  323. node = set->root;
  324. if (node != NULL)
  325. while (node->left != NULL)
  326. node = node->left;
  327. result.p = node;
  328. /* End point is past the rightmost node. */
  329. result.q = NULL;
  330. #if defined GCC_LINT || defined lint
  331. result.i = 0;
  332. result.j = 0;
  333. result.count = 0;
  334. #endif
  335. return result;
  336. }
  337. static gl_oset_iterator_t
  338. gl_tree_iterator_atleast (gl_oset_t set,
  339. gl_setelement_threshold_fn threshold_fn,
  340. const void *threshold)
  341. {
  342. gl_oset_iterator_t result;
  343. gl_oset_node_t node;
  344. result.vtable = set->base.vtable;
  345. result.set = set;
  346. /* End point is past the rightmost node. */
  347. result.q = NULL;
  348. #if defined GCC_LINT || defined lint
  349. result.i = 0;
  350. result.j = 0;
  351. result.count = 0;
  352. #endif
  353. for (node = set->root; node != NULL; )
  354. {
  355. if (! threshold_fn (node->value, threshold))
  356. node = node->right;
  357. else
  358. {
  359. /* We have an element >= THRESHOLD. But we need the leftmost such
  360. element. */
  361. gl_oset_node_t found = node;
  362. node = node->left;
  363. for (; node != NULL; )
  364. {
  365. if (! threshold_fn (node->value, threshold))
  366. node = node->right;
  367. else
  368. {
  369. found = node;
  370. node = node->left;
  371. }
  372. }
  373. result.p = found;
  374. return result;
  375. }
  376. }
  377. result.p = NULL;
  378. return result;
  379. }
  380. static bool
  381. gl_tree_iterator_next (gl_oset_iterator_t *iterator, const void **eltp)
  382. {
  383. if (iterator->p != iterator->q)
  384. {
  385. gl_oset_node_t node = (gl_oset_node_t) iterator->p;
  386. *eltp = node->value;
  387. /* Advance to the next node. */
  388. node = gl_tree_next_node (node);
  389. iterator->p = node;
  390. return true;
  391. }
  392. else
  393. return false;
  394. }
  395. static void
  396. gl_tree_iterator_free (gl_oset_iterator_t *iterator _GL_ATTRIBUTE_MAYBE_UNUSED)
  397. {
  398. }