libcstl
Loading...
Searching...
No Matches
bintree.c
Go to the documentation of this file.
1/*!
2 * @file
3 */
4
5#include "cstl/bintree.h"
6
7#include <assert.h>
8
9/*!
10 * @private
11 *
12 * Given a pointer to an element, return a (non-const) pointer
13 * to the cstl_bintree_node contained within it
14 */
15static struct cstl_bintree_node * __cstl_bintree_node(
16 const struct cstl_bintree * const bt, const void * p)
17{
18 return (struct cstl_bintree_node *)((uintptr_t)p + bt->off);
19}
20
21/*!
22 * @private
23 *
24 * Given a pointer to a node, get a (non-const) pointer
25 * to the element containing it
26 */
27static void * __cstl_bintree_element(
28 const struct cstl_bintree * const bt,
29 const struct cstl_bintree_node * const bn)
30{
31 return (void *)((uintptr_t)bn - bt->off);
32}
33
34/*!
35 * @private
36 *
37 * Given a pointer to a node, get a (const) pointer
38 * to the element containing it
39 */
40static const void * cstl_bintree_element(
41 const struct cstl_bintree * const bt,
42 const struct cstl_bintree_node * const bn)
43{
44 return __cstl_bintree_element(bt, bn);
45}
46
47/*!
48 * @private
49 *
50 * Compare the elements containing the given nodes using the cmp function
51 * associated with the tree. This function is called by other objects
52 * in the library that are based on the binary tree object
53 */
54int __cstl_bintree_cmp(const struct cstl_bintree * const bt,
55 const struct cstl_bintree_node * const a,
56 const struct cstl_bintree_node * const b)
57{
58 return bt->cmp.func(cstl_bintree_element(bt, a),
59 cstl_bintree_element(bt, b),
60 bt->cmp.priv);
61}
62
63void cstl_bintree_insert(struct cstl_bintree * const bt,
64 void * const e, void * const p)
65{
66 struct cstl_bintree_node * const bn = __cstl_bintree_node(bt, e);
67 struct cstl_bintree_node ** bc = &bt->root, * bp = *bc;
68
69 if (p != NULL) {
70 bp = __cstl_bintree_node(bt, p);
71 bc = &bp;
72 }
73
74 while (*bc != NULL) {
75 bp = *bc;
76
77 if (__cstl_bintree_cmp(bt, bn, bp) < 0) {
78 bc = &bp->l;
79 } else {
80 bc = &bp->r;
81 }
82 }
83
84 bn->p = bp;
85 bn->l = NULL;
86 bn->r = NULL;
87
88 *bc = bn;
89
90 bt->size++;
91}
92
93const void * cstl_bintree_find(const struct cstl_bintree * const bt,
94 const void * f,
95 const void ** const par)
96{
97 const struct cstl_bintree_node * const bf = __cstl_bintree_node(bt, f);
98 struct cstl_bintree_node * bn = bt->root, *p = NULL;
99
100 while (bn != NULL) {
101 const int eq = __cstl_bintree_cmp(bt, bf, bn);
102
103 if (eq == 0) {
104 break;
105 }
106
107 p = bn;
108 if (eq < 0) {
109 bn = bn->l;
110 } else {
111 bn = bn->r;
112 }
113 }
114
115 if (par != NULL) {
116 if (p == NULL) {
117 *par = NULL;
118 } else {
119 *par = __cstl_bintree_element(bt, p);
120 }
121 }
122
123 if (bn != NULL) {
124 return cstl_bintree_element(bt, bn);
125 }
126 return NULL;
127}
128
129/*!
130 * @private
131 *
132 * Given a node as a starting point, find the child furthest in
133 * the direction indicated by the function pointer @ch
134 */
135static inline struct cstl_bintree_node * cstl_bintree_slide(
136 const struct cstl_bintree_node * bn,
137 __cstl_bintree_child_func_t * const ch)
138{
139 struct cstl_bintree_node * c;
140
141 while ((c = *ch((struct cstl_bintree_node *)bn)) != NULL) {
142 bn = c;
143 }
144
145 return (struct cstl_bintree_node *)bn;
146}
147
148/*!
149 * @private
150 *
151 * Find node in the tree whose element's "value" immediately follows or
152 * precedes the given node's element's "value". whether the next or
153 * previous node is found is determined by the @l and @r functions.
154 *
155 * @see __cstl_bintree_next
156 * @see __cstl_bintree_prev
157 *
158 * inline comments below are for the "prev" case; they'd be reversed
159 * for finding the "next"
160 */
161static struct cstl_bintree_node * __cstl_bintree_adjacent(
162 const struct cstl_bintree_node * bn,
163 __cstl_bintree_child_func_t * const l,
164 __cstl_bintree_child_func_t * const r)
165{
166 struct cstl_bintree_node * const c = *l((struct cstl_bintree_node *)bn);
167
168 if (c != NULL) {
169 /*
170 * if the given node has a left (lesser) child,
171 * then the greatest value less than the given node,
172 * is the left child node's right-most child
173 */
174 bn = cstl_bintree_slide(c, r);
175 } else {
176 /*
177 * since there is no left child, do the reverse
178 * of the if clause: move up the tree while the current
179 * node is the left child. when it is not the left child
180 * (i.e. it is the right child), go up one more time.
181 *
182 * note that the root may be encountered before the above
183 * condition is satisfied, indicating that the desired
184 * value is not present in the tree
185 */
186 while (bn->p != NULL && *l((struct cstl_bintree_node *)bn->p) == bn) {
187 bn = bn->p;
188 }
189
190 bn = bn->p;
191 }
192
193 return (struct cstl_bintree_node *)bn;
194}
195
196/*!
197 * @private
198 *
199 * find the node whose element is the next greater value in the
200 * tree than the given node's element
201 */
202static struct cstl_bintree_node * __cstl_bintree_next(
203 const struct cstl_bintree_node * bn)
204{
205 return __cstl_bintree_adjacent(
206 bn, __cstl_bintree_right, __cstl_bintree_left);
207}
208
209/*!
210 * @private
211 *
212 * find the node whose element is the next lesser value in the
213 * tree than the given node's element
214 */
215static struct cstl_bintree_node * __cstl_bintree_prev(
216 const struct cstl_bintree_node * bn)
217{
218 return __cstl_bintree_adjacent(
219 bn, __cstl_bintree_left, __cstl_bintree_right);
220}
221
222/*!
223 * @private
224 *
225 * this function does the work of actually removing a node from
226 * the tree. if the node is a leaf or has only one child: the operation is
227 * simple: remove it, putting its child in its place if it had one. if the
228 * node has two children, find the next greater element in the tree--it will
229 * have one child, at most--remove it (as above) and swap it with the element
230 * that was supposed to be removed.
231 *
232 * returns a pointer to the location in the tree where the desired node
233 * was removed from. in the latter case described above, the returned
234 * pointer will actually point to a node still in the tree.
235 */
236const struct cstl_bintree_node * __cstl_bintree_erase(
237 struct cstl_bintree * const bt,
238 struct cstl_bintree_node * const bn)
239{
240 struct cstl_bintree_node * x, * y;
241
242 /*
243 * determine which node to remove: the given one if
244 * it has 0 or 1 children, otherwise the next greater one
245 */
246 if (bn->l != NULL && bn->r != NULL) {
247 y = __cstl_bintree_next(bn);
248 } else {
249 y = bn;
250 }
251
252 /* whichever one it is will/must have 1 child, at most */
253 assert(y->l == NULL || y->r == NULL);
254
255 /* if it had a child, point x at it */
256 if (y->l != NULL) {
257 x = y->l;
258 } else {
259 x = y->r;
260 }
261
262 /*
263 * if it had a child, it's new parent is
264 * y's parent (x's former grandparent)
265 */
266 if (x != NULL) {
267 x->p = y->p;
268 }
269
270 /*
271 * replace y with x as one of y's parent's children
272 */
273 if (y->p == NULL) {
274 bt->root = x;
275 } else if (y == y->p->l) {
276 y->p->l = x;
277 } else {
278 y->p->r = x;
279 }
280
281 /*
282 * at this point, y has been removed from the tree.
283 * if y was the desired node, then the work is done.
284 * if y was a different node, removed for convenience,
285 * y needs to be swapped back into the tree, replacing
286 * the node that was supposed to be removed.
287 */
288
289 if (y != bn) {
290 /* save y's pointers */
291 const struct cstl_bintree_node t = *y;
292
293 /*
294 * make the parent of the node that was supposed to
295 * be removed point to y is one of its children instead
296 * of the desired node
297 */
298 if (bn->p == NULL) {
299 bt->root = y;
300 } else if (bn == bn->p->l) {
301 bn->p->l = y;
302 } else {
303 bn->p->r = y;
304 }
305
306 /*
307 * modify the children of the node being removed
308 * to make y their new parent
309 */
310 if (bn->l != NULL) {
311 bn->l->p = y;
312 }
313 if (bn->r != NULL) {
314 bn->r->p = y;
315 }
316
317 /*
318 * y adopts all of the pointers belonging to
319 * the node being removed, and the node being
320 * removed adopts all of y's (saved) pointers
321 */
322 *y = *bn;
323 *bn = t;
324
325 /*
326 * it's possible that the (originally) removed node, y,
327 * was a direct descendant of bn (the node the caller
328 * wanted to remove). in this case, change bn's (formerly
329 * y's) parent to be y to more accurately reflect the state
330 * of things to the caller
331 */
332 if (bn->p == bn) {
333 bn->p = y;
334 }
335 }
336
337 bt->size--;
338
339 return y;
340}
341
342void * cstl_bintree_erase(struct cstl_bintree * const bt,
343 const void * const _p)
344{
345 void * p = (void *)cstl_bintree_find(bt, _p, NULL);
346
347 if (p != NULL) {
348 (void)__cstl_bintree_erase(bt, __cstl_bintree_node(bt, p));
349 }
350
351 return p;
352}
353
354/*!
355 * @private
356 *
357 * this operation is used by the red-black tree implementation, but
358 * since it operates on the binary tree, independent of any of the
359 * red-black additions, it is implemented here. it has the effect of
360 * modifying x and x's right child (y) such that y is put in place of
361 * x in the tree, x becomes y's left child, and y's (formerly) left
362 * child becomes x's new right child. the operation requires that
363 * x have a right child prior to calling the function.
364 *
365 * the operation can be reversed by reversing the @l and @r function
366 * pointers, in which case x must have a left child prior to calling
367 * the function
368 */
369void __cstl_bintree_rotate(struct cstl_bintree * const bt,
370 struct cstl_bintree_node * const x,
371 __cstl_bintree_child_func_t * const l,
372 __cstl_bintree_child_func_t * const r)
373{
374 struct cstl_bintree_node * const y = *r(x);
375 assert(y != NULL);
376
377 /* y's left child becomes x's right child */
378 *r(x) = *l(y);
379 if (*l(y) != NULL) {
380 (*l(y))->p = x;
381 }
382 /* y moves into x's position in the tree */
383 y->p = x->p;
384 if (x->p == NULL) {
385 bt->root = y;
386 } else if (x == *l(x->p)) {
387 *l(x->p) = y;
388 } else {
389 *r(x->p) = y;
390 }
391 /* x becomes y's left child */
392 *l(y) = x;
393 x->p = y;
394}
395
396/*!
397 * @private
398 *
399 * this version of the function operates on nodes rather than the tree,
400 * so it could be used to treat any given node as the root of the tree
401 * and walk the subtree rooted at that node. because of this property,
402 * the function also lends itself to being called recursively, which it
403 * is. whether the tree is traversed from left-to-right or right-to-left
404 * is determined by the @l and @r functions.
405 */
406static int __cstl_bintree_foreach(
407 const struct cstl_bintree_node * const _bn,
408 int (* const visit)(const struct cstl_bintree_node *,
410 void *),
411 void * const priv,
412 __cstl_bintree_child_func_t * const l,
413 __cstl_bintree_child_func_t * const r)
414{
415 struct cstl_bintree_node * const bn = (void *)_bn;
416 struct cstl_bintree_node * const ln = *l(bn), * const rn = *r(bn);
417 const int leaf = ln == NULL && rn == NULL;
418 int res = 0;
419
420 if (res == 0 && leaf == 0) {
421 /* first visit to the current node (if it's a non-leaf) */
422 res = visit(bn, CSTL_BINTREE_VISIT_ORDER_PRE, priv);
423 }
424
425 if (res == 0 && ln != NULL) {
426 /* visit the subtree rooted at the left child */
427 res = __cstl_bintree_foreach(ln, visit, priv, l, r);
428 }
429
430 if (res == 0) {
431 /* visit the current node */
432 if (leaf != 0) {
433 res = visit(bn, CSTL_BINTREE_VISIT_ORDER_LEAF, priv);
434 } else {
435 res = visit(bn, CSTL_BINTREE_VISIT_ORDER_MID, priv);
436 }
437 }
438
439 if (res == 0 && rn != NULL) {
440 /* visit the subtree rooted at the right child */
441 res = __cstl_bintree_foreach(rn, visit, priv, l, r);
442 }
443
444 if (res == 0 && leaf == 0) {
445 /* last visit to the current node (if it's a non-leaf) */
446 res = visit(bn, CSTL_BINTREE_VISIT_ORDER_POST, priv);
447 }
448
449 return res;
450}
451
452struct cstl_bintree_foreach_priv
453{
454 const struct cstl_bintree * bt;
456 void * priv;
457};
458
459/*!
460 * @private
461 *
462 * the __cstl_bintree_foreach function operates on tree nodes. this function
463 * translates the node pointer into an element pointer before calling
464 * the user-specified function
465 */
466static int cstl_bintree_foreach_visit(
467 const struct cstl_bintree_node * const bn,
468 const cstl_bintree_visit_order_t order,
469 void * const priv)
470{
471 struct cstl_bintree_foreach_priv * const bfp = priv;
472 return bfp->visit(cstl_bintree_element(bfp->bt, bn), order, bfp->priv);
473}
474
475int cstl_bintree_foreach(const struct cstl_bintree * const bt,
477 void * const priv,
479{
480 int res = 0;
481
482 if (bt->root != NULL) {
483 struct cstl_bintree_foreach_priv bfp;
484
485 bfp.bt = bt;
486 bfp.visit = visit;
487 bfp.priv = priv;
488
489 switch (dir) {
491 res = __cstl_bintree_foreach(
492 bt->root, cstl_bintree_foreach_visit, &bfp,
493 __cstl_bintree_left, __cstl_bintree_right);
494 break;
496 res = __cstl_bintree_foreach(
497 bt->root, cstl_bintree_foreach_visit, &bfp,
498 __cstl_bintree_right, __cstl_bintree_left);
499 break;
500 }
501 }
502
503 return res;
504}
505
506void cstl_bintree_swap(struct cstl_bintree * const a,
507 struct cstl_bintree * const b)
508{
509 struct cstl_bintree t;
510 cstl_swap(a, b, &t, sizeof(t));
511 /*
512 * the tree points to the root node, but
513 * the parent pointer of the root node
514 * is NULL, so no need to do any more
515 */
516}
517
518struct cstl_bintree_clear_priv
519{
520 struct cstl_bintree * bt;
521 cstl_xtor_func_t * clr;
522 void * priv;
523};
524
525/*!
526 * @private
527 *
528 * call the user specified clear function for each node in the tree.
529 * the call is only made for leaf nodes and on the last visit to non-leaf
530 * nodes. this ensures that the node isn't visited again after the call
531 * which means that the callee can modify the element however it wishes
532 * when called.
533 */
534static int __cstl_bintree_clear_visit(
535 const struct cstl_bintree_node * const bn,
536 const cstl_bintree_visit_order_t order,
537 void * const p)
538{
540 || order == CSTL_BINTREE_VISIT_ORDER_LEAF) {
541 struct cstl_bintree_clear_priv * const bcp = p;
542 /*
543 * explicitly ignore the callee's return value,
544 * and proceed through the tree, regardless
545 */
546 (void)bcp->clr(__cstl_bintree_element(bcp->bt, bn), bcp->priv);
547 }
548
549 return 0;
550}
551
552void cstl_bintree_clear(struct cstl_bintree * const bt,
553 cstl_xtor_func_t * const clr,
554 void * const priv)
555{
556 if (bt->root != NULL) {
557 struct cstl_bintree_clear_priv bcp;
558
559 bcp.bt = bt;
560 bcp.clr = clr;
561 bcp.priv = priv;
562
563 __cstl_bintree_foreach(bt->root, __cstl_bintree_clear_visit, &bcp,
564 __cstl_bintree_left, __cstl_bintree_right);
565
566 bt->root = NULL;
567 bt->size = 0;
568 }
569}
570
571struct cstl_bintree_height_priv
572{
573 size_t min, max;
574};
575
576/*!
577 * @private
578 *
579 * whenever a leaf node is encountered, walk up the tree from
580 * that node to the root, counting the number of nodes between.
581 * store that value if it is the new min and or max height
582 * encountered so far
583 */
584static int __cstl_bintree_height(const struct cstl_bintree_node * bn,
585 const cstl_bintree_visit_order_t order,
586 void * const priv)
587{
588 struct cstl_bintree_height_priv * const hp = priv;
589
590 if (order == CSTL_BINTREE_VISIT_ORDER_LEAF) {
591 size_t h;
592
593 for (h = 0; bn != NULL; h++, bn = bn->p)
594 ;
595
596 if (h < hp->min) {
597 hp->min = h;
598 }
599
600 if (h > hp->max) {
601 hp->max = h;
602 }
603 }
604
605 return 0;
606}
607
608void cstl_bintree_height(const struct cstl_bintree * const bt,
609 size_t * const min, size_t * const max)
610{
611 struct cstl_bintree_height_priv hp;
612
613 hp.min = 0;
614 hp.max = 0;
615
616 if (bt->root != NULL) {
617 hp.min = SIZE_MAX;
618 hp.max = 0;
619
620 __cstl_bintree_foreach(bt->root, __cstl_bintree_height, &hp,
621 __cstl_bintree_left, __cstl_bintree_right);
622 }
623
624 *min = hp.min;
625 *max = hp.max;
626}
627
628#ifdef __cfg_test__
629// GCOV_EXCL_START
630#include <check.h>
631#include <stdlib.h>
632
633static int __cstl_bintree_verify(const struct cstl_bintree_node * const bn,
634 const cstl_bintree_visit_order_t order,
635 void * const priv)
636{
638 || order == CSTL_BINTREE_VISIT_ORDER_LEAF) {
639 const struct cstl_bintree * const bt = priv;
640
641 if (bn->l != NULL) {
642 ck_assert_int_lt(__cstl_bintree_cmp(bt, bn->l, bn), 0);
643 }
644 if (bn->r != NULL) {
645 ck_assert_int_ge(__cstl_bintree_cmp(bt, bn->r, bn), 0);
646 }
647 }
648
649 return 0;
650}
651
652static void cstl_bintree_verify(const struct cstl_bintree * const bt)
653{
654 if (bt->root != NULL) {
655 __cstl_bintree_foreach(bt->root, __cstl_bintree_verify, (void *)bt,
656 __cstl_bintree_left, __cstl_bintree_right);
657 }
658}
659
660struct integer
661{
662 int v;
663 struct cstl_bintree_node bn;
664};
665
666static int cmp_integer(const void * const a, const void * const b,
667 void * const p)
668{
669 (void)p;
670 return ((struct integer *)a)->v - ((struct integer *)b)->v;
671}
672
673START_TEST(init)
674{
675 DECLARE_CSTL_BINTREE(bt, struct integer, bn, cmp_integer, NULL);
676 (void)bt;
677}
678END_TEST
679
680static void __test_cstl_bintree_free(void * const p, void * const x)
681{
682 (void)x;
683 free(p);
684}
685
686static void __test__cstl_bintree_fill(struct cstl_bintree * const bt,
687 const size_t n)
688{
689 unsigned int i;
690
691 for (i = 0; i < n; i++) {
692 struct integer * const in = malloc(sizeof(*in));
693
694 do {
695 in->v = rand() % n;
696 } while (cstl_bintree_find(bt, in, NULL) != NULL);
697
698 cstl_bintree_insert(bt, in, NULL);
699 ck_assert_uint_eq(i + 1, cstl_bintree_size(bt));
700
701 cstl_bintree_verify(bt);
702 }
703}
704
705static void __test__cstl_bintree_drain(struct cstl_bintree * const bt)
706{
707 size_t sz;
708
709 while ((sz = cstl_bintree_size(bt)) > 0) {
710 struct cstl_bintree_node * bn = bt->root;
711
712 __cstl_bintree_erase(bt, bn);
713 free((void *)cstl_bintree_element(bt, bn));
714
715 ck_assert_uint_eq(sz - 1, cstl_bintree_size(bt));
716
717 cstl_bintree_verify(bt);
718 }
719
720 ck_assert_ptr_null(bt->root);
721 ck_assert_uint_eq(cstl_bintree_size(bt), 0);
722}
723
724START_TEST(fill)
725{
726 static const size_t n = 100;
727
728 DECLARE_CSTL_BINTREE(bt1, struct integer, bn, cmp_integer, NULL);
729 DECLARE_CSTL_BINTREE(bt2, struct integer, bn, cmp_integer, NULL);
730
731 __test__cstl_bintree_fill(&bt1, n);
732 {
733 size_t min, max;
734 cstl_bintree_height(&bt1, &min, &max);
735 ck_assert_uint_gt(min, 0);
736 ck_assert_uint_gt(max, 0);
737 cstl_bintree_swap(&bt1, &bt2);
738 cstl_bintree_height(&bt1, &min, &max);
739 ck_assert_uint_eq(min, 0);
740 ck_assert_uint_eq(max, 0);
741 }
742 __test__cstl_bintree_drain(&bt2);
743 __test__cstl_bintree_drain(&bt1);
744}
745END_TEST
746
747static int __test__foreach_fwd_visit(const void * const v,
748 const cstl_bintree_visit_order_t order,
749 void * const p)
750{
752 || order == CSTL_BINTREE_VISIT_ORDER_LEAF) {
753 const struct integer * const in = v;
754 unsigned int * const i = p;
755
756 ck_assert_uint_eq(*i, in->v);
757 (*i)++;
758 }
759
760 return 0;
761}
762
763START_TEST(walk_fwd)
764{
765 static const size_t n = 100;
766
767 DECLARE_CSTL_BINTREE(bt, struct integer, bn, cmp_integer, NULL);
768 struct cstl_bintree_node * node;
769 unsigned int i;
770
771 __test__cstl_bintree_fill(&bt, n);
772
773 i = 0;
775 __test__foreach_fwd_visit, &i,
777
778 node = cstl_bintree_slide(bt.root, __cstl_bintree_left);
779 ck_assert_ptr_nonnull(node);
780 i = 0;
781 while (node != NULL) {
782 const struct integer * const in = __cstl_bintree_element(&bt, node);
783 ck_assert_uint_eq(i, in->v);
784 i++;
785 node = __cstl_bintree_next(node);
786 }
787
788 cstl_bintree_clear(&bt, __test_cstl_bintree_free, NULL);
789}
790END_TEST
791
792static int __test__foreach_rev_visit(const void * const v,
793 const cstl_bintree_visit_order_t order,
794 void * const p)
795{
797 || order == CSTL_BINTREE_VISIT_ORDER_LEAF) {
798 const struct integer * const in = v;
799 unsigned int * const i = p;
800
801 (*i)--;
802 ck_assert_uint_eq(*i, in->v);
803 }
804
805 return 0;
806}
807
808START_TEST(walk_rev)
809{
810 static const size_t n = 100;
811
812 DECLARE_CSTL_BINTREE(bt, struct integer, bn, cmp_integer, NULL);
813 struct cstl_bintree_node * node;
814 unsigned int i;
815
816 __test__cstl_bintree_fill(&bt, n);
817
818 i = n;
820 __test__foreach_rev_visit, &i,
822
823 node = cstl_bintree_slide(bt.root, __cstl_bintree_right);
824 ck_assert_ptr_nonnull(node);
825 i = n;
826 while (node != NULL) {
827 const struct integer * const in = __cstl_bintree_element(&bt, node);
828 i--;
829 ck_assert_uint_eq(i, in->v);
830 node = __cstl_bintree_prev(node);
831 }
832
833 cstl_bintree_clear(&bt, __test_cstl_bintree_free, NULL);
834}
835END_TEST
836
837START_TEST(random_empty)
838{
839 static const size_t n = 100;
840
841 DECLARE_CSTL_BINTREE(bt, struct integer, bn, cmp_integer, NULL);
842 size_t sz;
843
844 __test__cstl_bintree_fill(&bt, n);
845
846 while ((sz = cstl_bintree_size(&bt)) > 0) {
847 struct integer _in, * in;
848
849 _in.v = rand() % n;
850
851 in = cstl_bintree_erase(&bt, &_in);
852 if (in != NULL) {
853 free(in);
854 ck_assert_uint_eq(sz - 1, cstl_bintree_size(&bt));
855 }
856 }
857
858 ck_assert_ptr_null(bt.root);
859 ck_assert_uint_eq(bt.size, 0);
860}
861END_TEST
862
863Suite * bintree_suite(void)
864{
865 Suite * const s = suite_create("bintree");
866
867 TCase * tc;
868
869 tc = tcase_create("bintree");
870 tcase_add_test(tc, init);
871 tcase_add_test(tc, fill);
872 tcase_add_test(tc, walk_fwd);
873 tcase_add_test(tc, walk_rev);
874 tcase_add_test(tc, random_empty);
875
876 suite_add_tcase(s, tc);
877
878 return s;
879}
880
881// GCOV_EXCL_STOP
882#endif
static void cstl_swap(void *const x, void *const y, void *const t, const size_t sz)
Swap values at two memory locations via use of a third.
Definition common.h:137
void cstl_xtor_func_t(void *obj, void *priv)
Type for functions called to construct, clear, or destroy an object.
Definition common.h:97
void cstl_bintree_insert(struct cstl_bintree *const bt, void *const e, void *const p)
Insert a new object into the tree.
Definition bintree.c:63
cstl_bintree_visit_order_t
Enumeration indicating the order in which a tree element is being visited during cstl_bintree_foreach...
Definition bintree.h:249
static size_t cstl_bintree_size(const struct cstl_bintree *const bt)
Get the number of objects in the tree.
Definition bintree.h:149
#define DECLARE_CSTL_BINTREE(NAME, TYPE, MEMB, CMP, PRIV)
(Statically) declare and initialize a binary tree
Definition bintree.h:114
cstl_bintree_foreach_dir_t
Enumeration indicating the order in which elements in a tree are visited during cstl_bintree_foreach(...
Definition bintree.h:275
int cstl_bintree_const_visit_func_t(const void *e, cstl_bintree_visit_order_t ord, void *p)
The type of visit function associated with cstl_bintree_foreach()
Definition bintree.h:299
void cstl_bintree_height(const struct cstl_bintree *const bt, size_t *const min, size_t *const max)
Determine the maximum and minimum heights of a tree.
Definition bintree.c:608
int cstl_bintree_foreach(const struct cstl_bintree *const bt, cstl_bintree_const_visit_func_t *const visit, void *const priv, const cstl_bintree_foreach_dir_t dir)
Visit each element in a tree, calling a user-defined function for each visit.
Definition bintree.c:475
const void * cstl_bintree_find(const struct cstl_bintree *const bt, const void *f, const void **const par)
Find an element within a tree.
Definition bintree.c:93
void cstl_bintree_swap(struct cstl_bintree *const a, struct cstl_bintree *const b)
Swap the tree objects at the two given locations.
Definition bintree.c:506
void * cstl_bintree_erase(struct cstl_bintree *const bt, const void *const _p)
Remove an element from the tree.
Definition bintree.c:342
void cstl_bintree_clear(struct cstl_bintree *const bt, cstl_xtor_func_t *const clr, void *const priv)
Remove all elements from the tree.
Definition bintree.c:552
@ CSTL_BINTREE_VISIT_ORDER_LEAF
The only visit to an element that has no children.
Definition bintree.h:263
@ CSTL_BINTREE_VISIT_ORDER_POST
The last visit to an element, after both children have/would have been visited.
Definition bintree.h:261
@ CSTL_BINTREE_VISIT_ORDER_MID
The second visit to an element, after its first child has/would have been visited.
Definition bintree.h:256
@ CSTL_BINTREE_VISIT_ORDER_PRE
The first visit to an element that has at least one child.
Definition bintree.h:251
@ CSTL_BINTREE_FOREACH_DIR_REV
Each element in the tree is visited from right-to-left.
Definition bintree.h:279
@ CSTL_BINTREE_FOREACH_DIR_FWD
Each element in the tree is visited from left-to-right.
Definition bintree.h:277
Node to anchor an element within a binary tree.
Definition bintree.h:49
Binary tree object.
Definition bintree.h:63