From 85a363d32536861a4558bc8c193e505f2b58b43d Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Fri, 16 Jul 2021 22:46:44 +0200 Subject: [PATCH] Update definition of returned iterator of _it_from of RB tree from the greatest element of 'rbtree' lower of equal than 'data' to the lowest element of the tree 'rbtree' greater or equal than 'data' It is more logical and natural: if you have a tree of elements between [2, 4], and you want to iterate all elements from 0 to 10, the old definition doesn't allow you to iterate easily over this subset. --- README.md | 2 +- m-rbtree.h | 12 ++++++++---- tests/test-mrbtree.c | 40 ++++++++++++++++++++++++---------------- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index b8ec7033..1ab8fc95 100644 --- a/README.md +++ b/README.md @@ -2818,7 +2818,7 @@ Set the iterator 'it' to no element of 'rbtree'. ##### void name\_it\_from(name\_it\_t it, const name\_t rbtree, const type data) Set the iterator 'it' to -the greatest element of 'rbtree' lower of equal than 'data' +the lowest element of the tree 'rbtree' greater or equal than 'data' or an iterator to no element is there is none. ##### bool name\_end\_p(const name\_it\_t it) diff --git a/m-rbtree.h b/m-rbtree.h index 33bc187f..d53dbabe 100644 --- a/m-rbtree.h +++ b/m-rbtree.h @@ -570,9 +570,9 @@ typedef enum { M_RBTR33_CONTRACT (tree); \ M_ASSERT (it != NULL); \ unsigned int cpt = 0; \ - int cmp = -1; \ + int cmp = 1; \ node_t *n = tree->node; \ - /* Find the greatest element lower or equal than data in the tree */ \ + /* Find the lowest element greater or equal than data in the tree */ \ while (n != NULL) { \ M_ASSERT (cpt < M_RBTR33_MAX_STACK); \ it->which[cpt] = 0; \ @@ -584,9 +584,13 @@ typedef enum { it->which[cpt-1] = (int8_t) child; \ n = n->child[child]; \ } \ - /* If the lowest element is still greater than data, invalid iterator */ \ - if (cmp > 0) cpt = 0; \ + /* Save the iterator */ \ it->cpt = cpt; \ + /* The iterator found may be strictly lower than data. \ + In this case, go to the next element */ \ + if (cmp < 0) { \ + M_C(name, _next)(it); \ + } \ } \ \ static inline bool \ diff --git a/tests/test-mrbtree.c b/tests/test-mrbtree.c index c42e6592..94df559d 100644 --- a/tests/test-mrbtree.c +++ b/tests/test-mrbtree.c @@ -351,11 +351,6 @@ static void test_from(void) assert(!rbtree_uint_it_while_p(it, 2)); rbtree_uint_it_from(it, tree, 2); - assert(rbtree_uint_end_p(it)); - assert(rbtree_uint_it_until_p(it, 3)); - assert(!rbtree_uint_it_while_p(it, 3)); - - rbtree_uint_it_from(it, tree, 4); assert(!rbtree_uint_end_p(it)); assert(rbtree_uint_it_until_p(it, 3)); assert(rbtree_uint_it_while_p(it, 3)); @@ -364,6 +359,11 @@ static void test_from(void) assert(rbtree_uint_it_until_p(it, 2)); assert(!rbtree_uint_it_while_p(it, 2)); + rbtree_uint_it_from(it, tree, 4); + assert(rbtree_uint_end_p(it)); + assert(rbtree_uint_it_until_p(it, 3)); + assert(!rbtree_uint_it_while_p(it, 3)); + // More elements rbtree_uint_push(tree, 10); rbtree_uint_push(tree, 5); @@ -410,24 +410,32 @@ static void test_from(void) } assert(k == 2); - // No element is lower or equal than 0 ==> The set is empty k = 0; + const unsigned int tab1[] = { 1, 3, 5}; for( rbtree_uint_it_from(it, tree, 0); rbtree_uint_it_while_p(it, 6); rbtree_uint_next(it)) { assert (k < 3); - assert(tab0[k] == *rbtree_uint_cref(it)); - k++; - } - assert(k == 0); - - // The iteration starts from 3 which is lower or equal than 4. - k = 0; - for( rbtree_uint_it_from(it, tree, 4); rbtree_uint_it_while_p(it, 7); rbtree_uint_next(it)) { - assert (k < 3); - assert(tab0[k] == *rbtree_uint_cref(it)); + assert(tab1[k] == *rbtree_uint_cref(it)); k++; } assert(k == 3); + k = 0; + const unsigned int tab2[] = { 5, 7}; + for( rbtree_uint_it_from(it, tree, 4); rbtree_uint_it_while_p(it, 7); rbtree_uint_next(it)) { + assert (k < 2); + assert(tab2[k] == *rbtree_uint_cref(it)); + k++; + } + assert(k == 2); + + // From higher than all elements in the tree ==> no iterator. + k = 0; + for( rbtree_uint_it_from(it, tree, 11); rbtree_uint_it_while_p(it, 17); rbtree_uint_next(it)) { + assert (k < 2); + k++; + } + assert(k == 0); + rbtree_uint_clear(tree); }