Change Semantics of r_rbtree_upper_bound() and simplify Iter Fcns (#15698)

This commit is contained in:
Florian Märkl 2019-12-23 17:21:20 +01:00 committed by GitHub
parent f13802b4f8
commit 2a27daac4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 80 additions and 43 deletions

View File

@ -67,21 +67,18 @@ R_API void r_rbtree_free(RBNode *root, RBNodeFree freefn, void *user);
R_API void r_rbtree_insert(RBNode **root, void *data, RBNode *node, RBComparator cmp, void *user);
// Return the smallest node that is greater than or equal to `data`
R_API RBNode *r_rbtree_lower_bound(RBNode *root, void *data, RBComparator cmp, void *user);
// Return the smallest node that is greater than `data`
// Return the greatest node that is less than or equal to `data`
R_API RBNode *r_rbtree_upper_bound(RBNode *root, void *data, RBComparator cmp, void *user);
// Create a forward iterator starting from the leftmost node
R_API RBIter r_rbtree_first(RBNode *root);
// Create a backward iterator starting from the rightmost node
R_API RBIter r_rbtree_last(RBNode *root);
// Iterate [lower_bound, end) forward, used with r_rbtree_iter_next
R_API RBIter r_rbtree_lower_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user);
// Iterate [begin, lower_bound) backward, used with r_rbtree_iter_prev
// Iterate [lower_bound, end] forward, used with r_rbtree_iter_next
R_API RBIter r_rbtree_lower_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user);
// Iterate [upper_bound, end) forward, used with r_rbtree_iter_next
// Iterate [begin, upper_bound] backward, used with r_rbtree_iter_prev
R_API RBIter r_rbtree_upper_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user);
// Iterate [begin, upper_bound) backward, used with r_rbtree_iter_prev
R_API RBIter r_rbtree_upper_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user);
// struct Node { int key; RBNode rb; };
// r_rbtree_iter_get (it, struct Node, rb)

View File

@ -36,23 +36,30 @@ static inline RBNode *zig_zag(RBNode *x, int dir, RBNodeSum sum) {
return z;
}
static inline RBIter bound_iter(RBNode *x, void *data, RBComparator cmp, bool upper, bool backward, void *user) {
static inline RBIter bound_iter(RBNode *x, void *data, RBComparator cmp, bool upper, void *user) {
RBIter it;
it.len = 0;
while (x) {
int d = cmp (data, x, user);
if (upper ? d < 0 : d <= 0) {
if (!backward) {
if (d == 0) {
it.path[it.len++] = x;
return it;
}
if (d < 0) {
if (!upper) {
it.path[it.len++] = x;
}
x = x->child[0];
} else {
if (backward) {
if (upper) {
it.path[it.len++] = x;
}
x = x->child[1];
}
}
return it;
}
@ -323,12 +330,8 @@ R_API RBNode *r_rbtree_lower_bound(RBNode *x, void *data, RBComparator cmp, void
return ret;
}
R_API RBIter r_rbtree_lower_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user) {
return bound_iter (root, data, cmp, false, true, user);
}
R_API RBIter r_rbtree_lower_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user) {
return bound_iter (root, data, cmp, false, false, user);
return bound_iter (root, data, cmp, false, user);
}
R_API RBNode *r_rbtree_upper_bound(RBNode *x, void *data, RBComparator cmp, void *user) {
@ -336,9 +339,9 @@ R_API RBNode *r_rbtree_upper_bound(RBNode *x, void *data, RBComparator cmp, void
while (x) {
int d = cmp (data, x, user);
if (d < 0) {
ret = x;
x = x->child[0];
} else {
ret = x;
x = x->child[1];
}
}
@ -346,11 +349,7 @@ R_API RBNode *r_rbtree_upper_bound(RBNode *x, void *data, RBComparator cmp, void
}
R_API RBIter r_rbtree_upper_bound_backward(RBNode *root, void *data, RBComparator cmp, void *user) {
return bound_iter (root, data, cmp, true, true, user);
}
R_API RBIter r_rbtree_upper_bound_forward(RBNode *root, void *data, RBComparator cmp, void *user) {
return bound_iter (root, data, cmp, true, false, user);
return bound_iter (root, data, cmp, true, user);
}
static RBIter _first(RBNode *x, int dir) {

View File

@ -80,9 +80,8 @@ bool check(RBNode *tree) {
return check1 (tree, 0, 0, true);
}
bool test_r_rbtree_bound(void) {
const int key1 = 0x24;
struct Node key = {.key = key1};
bool test_r_rbtree_bound_iterate() {
struct Node key = { 0 };
RBIter it;
RBNode *tree = NULL;
struct Node *x;
@ -92,42 +91,83 @@ bool test_r_rbtree_bound(void) {
mu_assert_eq (f.len, 0, "iter with 0 length");
for (i = 0; i < 99; i++) {
x = make (i);
x = make (i * 2);
r_rbtree_insert (&tree, x, &x->rb, cmp, NULL);
}
// lower_bound
key.key = 0x24;
it = r_rbtree_lower_bound_forward (tree, &key, cmp, NULL);
i = key1;
i = 0x24;
r_rbtree_iter_while (it, x, struct Node, rb) {
mu_assert_eq (i, x->key, "lower_bound_forward");
i++;
mu_assert_eq (x->key, i, "lower_bound_forward equal");
i += 2;
}
it = r_rbtree_lower_bound_backward (tree, &key, cmp, NULL);
i = key1 - 1;
r_rbtree_iter_while_prev (it, x, struct Node, rb) {
mu_assert_eq (i, x->key, "lower_bound_backward");
i--;
mu_assert_eq (i - 2, 98 * 2, "lower_bound_forward complete");
key.key = 0x25;
it = r_rbtree_lower_bound_forward (tree, &key, cmp, NULL);
i = 0x26;
r_rbtree_iter_while (it, x, struct Node, rb) {
mu_assert_eq (x->key, i, "lower_bound_forward more");
i += 2;
}
mu_assert_eq (i - 2, 98 * 2, "lower_bound_forward complete");
// upper_bound
it = r_rbtree_upper_bound_forward (tree, &key, cmp, NULL);
i = key1 + 1;
r_rbtree_iter_while (it, x, struct Node, rb) {
mu_assert_eq (i, x->key, "upper_bound_forward");
i++;
}
key.key = 0x24;
it = r_rbtree_upper_bound_backward (tree, &key, cmp, NULL);
i = key1;
i = 0x24;
r_rbtree_iter_while_prev (it, x, struct Node, rb) {
mu_assert_eq (i, x->key, "upper_bound_backward");
i--;
mu_assert_eq (x->key, i, "upper_bound_backward");
i -= 2;
}
mu_assert_eq (i + 2, 0, "upper_bound_backward complete");
key.key = 0x25;
it = r_rbtree_upper_bound_backward (tree, &key, cmp, NULL);
i = 0x24;
r_rbtree_iter_while_prev (it, x, struct Node, rb) {
mu_assert_eq (x->key, i, "upper_bound_backward less");
i -= 2;
}
mu_assert_eq (i + 2, 0, "upper_bound_backward complete");
r_rbtree_free (tree, freefn, NULL);
mu_end;
}
bool test_r_rbtree_bound() {
struct Node key = { 0 };
RBIter it;
RBNode *tree = NULL;
struct Node *x;
int i;
for (i = 0; i < 99; i++) {
x = make (i*2);
r_rbtree_insert (&tree, x, &x->rb, cmp, NULL);
}
key.key = 0x24;
x = container_of (r_rbtree_lower_bound (tree, &key, cmp, NULL), struct Node, rb);
mu_assert_eq (x->key, 0x24, "lower bound equal");
key.key = 0x25;
x = container_of (r_rbtree_lower_bound (tree, &key, cmp, NULL), struct Node, rb);
mu_assert_eq (x->key, 0x26, "lower bound more");
key.key = 0x24;
x = container_of (r_rbtree_upper_bound (tree, &key, cmp, NULL), struct Node, rb);
mu_assert_eq (x->key, 0x24, "upper bound equal");
key.key = 0x25;
x = container_of (r_rbtree_upper_bound (tree, &key, cmp, NULL), struct Node, rb);
mu_assert_eq (x->key, 0x24, "upper bound less");
mu_end;
}
static bool insert_delete(int *a, int n, RBNodeSum sum) {
RBNode *tree = NULL;
struct Node *x;
@ -261,6 +301,7 @@ bool test_r_rbtree_traverse(void) {
int all_tests() {
mu_run_test (test_r_rbtree_bound);
mu_run_test (test_r_rbtree_bound_iterate);
mu_run_test (test_r_rbtree_insert_delete);
mu_run_test (test_r_rbtree_traverse);
mu_run_test (test_r_rbtree_augmented_insert_delete);