27static void * __cstl_bintree_element(
31 return (
void *)((uintptr_t)bn - bt->off);
40static const void * cstl_bintree_element(
44 return __cstl_bintree_element(bt, bn);
54int __cstl_bintree_cmp(
const struct cstl_bintree *
const bt,
58 return bt->cmp.func(cstl_bintree_element(bt, a),
59 cstl_bintree_element(bt, b),
64 void *
const e,
void *
const p)
70 bp = __cstl_bintree_node(bt, p);
77 if (__cstl_bintree_cmp(bt, bn, bp) < 0) {
95 const void **
const par)
101 const int eq = __cstl_bintree_cmp(bt, bf, bn);
119 *par = __cstl_bintree_element(bt, p);
124 return cstl_bintree_element(bt, bn);
137 __cstl_bintree_child_func_t *
const ch)
163 __cstl_bintree_child_func_t *
const l,
164 __cstl_bintree_child_func_t *
const r)
174 bn = cstl_bintree_slide(c, r);
205 return __cstl_bintree_adjacent(
206 bn, __cstl_bintree_right, __cstl_bintree_left);
218 return __cstl_bintree_adjacent(
219 bn, __cstl_bintree_left, __cstl_bintree_right);
246 if (bn->l != NULL && bn->r != NULL) {
247 y = __cstl_bintree_next(bn);
253 assert(y->l == NULL || y->r == NULL);
275 }
else if (y == y->p->l) {
300 }
else if (bn == bn->p->l) {
343 const void *
const _p)
348 (void)__cstl_bintree_erase(bt, __cstl_bintree_node(bt, p));
369void __cstl_bintree_rotate(
struct cstl_bintree *
const bt,
371 __cstl_bintree_child_func_t *
const l,
372 __cstl_bintree_child_func_t *
const r)
386 }
else if (x == *l(x->p)) {
406static int __cstl_bintree_foreach(
412 __cstl_bintree_child_func_t *
const l,
413 __cstl_bintree_child_func_t *
const r)
417 const int leaf = ln == NULL && rn == NULL;
420 if (res == 0 && leaf == 0) {
425 if (res == 0 && ln != NULL) {
427 res = __cstl_bintree_foreach(ln, visit, priv, l, r);
439 if (res == 0 && rn != NULL) {
441 res = __cstl_bintree_foreach(rn, visit, priv, l, r);
444 if (res == 0 && leaf == 0) {
452struct cstl_bintree_foreach_priv
466static int cstl_bintree_foreach_visit(
471 struct cstl_bintree_foreach_priv *
const bfp = priv;
472 return bfp->visit(cstl_bintree_element(bfp->bt, bn), order, bfp->priv);
482 if (bt->root != NULL) {
483 struct cstl_bintree_foreach_priv bfp;
491 res = __cstl_bintree_foreach(
492 bt->root, cstl_bintree_foreach_visit, &bfp,
493 __cstl_bintree_left, __cstl_bintree_right);
496 res = __cstl_bintree_foreach(
497 bt->root, cstl_bintree_foreach_visit, &bfp,
498 __cstl_bintree_right, __cstl_bintree_left);
518struct cstl_bintree_clear_priv
534static int __cstl_bintree_clear_visit(
541 struct cstl_bintree_clear_priv *
const bcp = p;
546 (void)bcp->clr(__cstl_bintree_element(bcp->bt, bn), bcp->priv);
556 if (bt->root != NULL) {
557 struct cstl_bintree_clear_priv bcp;
563 __cstl_bintree_foreach(bt->root, __cstl_bintree_clear_visit, &bcp,
564 __cstl_bintree_left, __cstl_bintree_right);
571struct cstl_bintree_height_priv
588 struct cstl_bintree_height_priv *
const hp = priv;
593 for (h = 0; bn != NULL; h++, bn = bn->p)
609 size_t *
const min,
size_t *
const max)
611 struct cstl_bintree_height_priv hp;
616 if (bt->root != NULL) {
620 __cstl_bintree_foreach(bt->root, __cstl_bintree_height, &hp,
621 __cstl_bintree_left, __cstl_bintree_right);
642 ck_assert_int_lt(__cstl_bintree_cmp(bt, bn->l, bn), 0);
645 ck_assert_int_ge(__cstl_bintree_cmp(bt, bn->r, bn), 0);
652static void cstl_bintree_verify(
const struct cstl_bintree *
const bt)
654 if (bt->root != NULL) {
655 __cstl_bintree_foreach(bt->root, __cstl_bintree_verify, (
void *)bt,
656 __cstl_bintree_left, __cstl_bintree_right);
666static int cmp_integer(
const void *
const a,
const void *
const b,
670 return ((
struct integer *)a)->v - ((
struct integer *)b)->v;
680static void __test_cstl_bintree_free(
void *
const p,
void *
const x)
686static void __test__cstl_bintree_fill(
struct cstl_bintree *
const bt,
691 for (i = 0; i < n; i++) {
692 struct integer *
const in = malloc(
sizeof(*in));
701 cstl_bintree_verify(bt);
705static void __test__cstl_bintree_drain(
struct cstl_bintree *
const bt)
712 __cstl_bintree_erase(bt, bn);
713 free((
void *)cstl_bintree_element(bt, bn));
717 cstl_bintree_verify(bt);
720 ck_assert_ptr_null(bt->root);
726 static const size_t n = 100;
731 __test__cstl_bintree_fill(&bt1, n);
735 ck_assert_uint_gt(min, 0);
736 ck_assert_uint_gt(max, 0);
739 ck_assert_uint_eq(min, 0);
740 ck_assert_uint_eq(max, 0);
742 __test__cstl_bintree_drain(&bt2);
743 __test__cstl_bintree_drain(&bt1);
747static int __test__foreach_fwd_visit(
const void *
const v,
753 const struct integer *
const in = v;
754 unsigned int *
const i = p;
756 ck_assert_uint_eq(*i, in->v);
765 static const size_t n = 100;
771 __test__cstl_bintree_fill(&bt, n);
775 __test__foreach_fwd_visit, &i,
778 node = cstl_bintree_slide(bt.root, __cstl_bintree_left);
779 ck_assert_ptr_nonnull(node);
781 while (node != NULL) {
782 const struct integer *
const in = __cstl_bintree_element(&bt, node);
783 ck_assert_uint_eq(i, in->v);
785 node = __cstl_bintree_next(node);
792static int __test__foreach_rev_visit(
const void *
const v,
798 const struct integer *
const in = v;
799 unsigned int *
const i = p;
802 ck_assert_uint_eq(*i, in->v);
810 static const size_t n = 100;
816 __test__cstl_bintree_fill(&bt, n);
820 __test__foreach_rev_visit, &i,
823 node = cstl_bintree_slide(bt.root, __cstl_bintree_right);
824 ck_assert_ptr_nonnull(node);
826 while (node != NULL) {
827 const struct integer *
const in = __cstl_bintree_element(&bt, node);
829 ck_assert_uint_eq(i, in->v);
830 node = __cstl_bintree_prev(node);
837START_TEST(random_empty)
839 static const size_t n = 100;
844 __test__cstl_bintree_fill(&bt, n);
847 struct integer _in, * in;
858 ck_assert_ptr_null(bt.root);
859 ck_assert_uint_eq(bt.size, 0);
863Suite * bintree_suite(
void)
865 Suite *
const s = suite_create(
"bintree");
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);
876 suite_add_tcase(s, tc);
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.
void cstl_xtor_func_t(void *obj, void *priv)
Type for functions called to construct, clear, or destroy an object.
void cstl_bintree_insert(struct cstl_bintree *const bt, void *const e, void *const p)
Insert a new object into the tree.
cstl_bintree_visit_order_t
Enumeration indicating the order in which a tree element is being visited during cstl_bintree_foreach...
static size_t cstl_bintree_size(const struct cstl_bintree *const bt)
Get the number of objects in the tree.
#define DECLARE_CSTL_BINTREE(NAME, TYPE, MEMB, CMP, PRIV)
(Statically) declare and initialize a binary tree
cstl_bintree_foreach_dir_t
Enumeration indicating the order in which elements in a tree are visited during cstl_bintree_foreach(...
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()
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.
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.
const void * cstl_bintree_find(const struct cstl_bintree *const bt, const void *f, const void **const par)
Find an element within a tree.
void cstl_bintree_swap(struct cstl_bintree *const a, struct cstl_bintree *const b)
Swap the tree objects at the two given locations.
void * cstl_bintree_erase(struct cstl_bintree *const bt, const void *const _p)
Remove an element from the tree.
void cstl_bintree_clear(struct cstl_bintree *const bt, cstl_xtor_func_t *const clr, void *const priv)
Remove all elements from the tree.
@ CSTL_BINTREE_VISIT_ORDER_LEAF
The only visit to an element that has no children.
@ CSTL_BINTREE_VISIT_ORDER_POST
The last visit to an element, after both children have/would have been visited.
@ CSTL_BINTREE_VISIT_ORDER_MID
The second visit to an element, after its first child has/would have been visited.
@ CSTL_BINTREE_VISIT_ORDER_PRE
The first visit to an element that has at least one child.
@ CSTL_BINTREE_FOREACH_DIR_REV
Each element in the tree is visited from right-to-left.
@ CSTL_BINTREE_FOREACH_DIR_FWD
Each element in the tree is visited from left-to-right.
Node to anchor an element within a binary tree.