Remove rbt_nil
Since this is an intrusive tree, rbt_nil is the whole size of the node and can be quite large. For example, miscelm is ~100 bytes.
This commit is contained in:
parent
0da8ce1e96
commit
2b1fc90b7b
@ -42,7 +42,6 @@ struct { \
|
|||||||
#define rb_tree(a_type) \
|
#define rb_tree(a_type) \
|
||||||
struct { \
|
struct { \
|
||||||
a_type *rbt_root; \
|
a_type *rbt_root; \
|
||||||
a_type rbt_nil; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Left accessors. */
|
/* Left accessors. */
|
||||||
@ -84,8 +83,8 @@ struct { \
|
|||||||
#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
|
#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
|
||||||
/* Bookkeeping bit cannot be used by node pointer. */ \
|
/* Bookkeeping bit cannot be used by node pointer. */ \
|
||||||
assert(((uintptr_t)(a_node) & 0x1) == 0); \
|
assert(((uintptr_t)(a_node) & 0x1) == 0); \
|
||||||
rbtn_left_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \
|
rbtn_left_set(a_type, a_field, (a_node), NULL); \
|
||||||
rbtn_right_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \
|
rbtn_right_set(a_type, a_field, (a_node), NULL); \
|
||||||
rbtn_red_set(a_type, a_field, (a_node)); \
|
rbtn_red_set(a_type, a_field, (a_node)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
@ -111,25 +110,23 @@ struct { \
|
|||||||
|
|
||||||
/* Node initializer. */
|
/* Node initializer. */
|
||||||
#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
|
#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \
|
||||||
rbtn_left_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \
|
rbtn_left_set(a_type, a_field, (a_node), NULL); \
|
||||||
rbtn_right_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \
|
rbtn_right_set(a_type, a_field, (a_node), NULL); \
|
||||||
rbtn_red_set(a_type, a_field, (a_node)); \
|
rbtn_red_set(a_type, a_field, (a_node)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Tree initializer. */
|
/* Tree initializer. */
|
||||||
#define rb_new(a_type, a_field, a_rbt) do { \
|
#define rb_new(a_type, a_field, a_rbt) do { \
|
||||||
(a_rbt)->rbt_root = &(a_rbt)->rbt_nil; \
|
(a_rbt)->rbt_root = NULL; \
|
||||||
rbt_node_new(a_type, a_field, a_rbt, &(a_rbt)->rbt_nil); \
|
|
||||||
rbtn_black_set(a_type, a_field, &(a_rbt)->rbt_nil); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* Internal utility macros. */
|
/* Internal utility macros. */
|
||||||
#define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \
|
#define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \
|
||||||
(r_node) = (a_root); \
|
(r_node) = (a_root); \
|
||||||
if ((r_node) != &(a_rbt)->rbt_nil) { \
|
if ((r_node) != NULL) { \
|
||||||
for (; \
|
for (; \
|
||||||
rbtn_left_get(a_type, a_field, (r_node)) != &(a_rbt)->rbt_nil;\
|
rbtn_left_get(a_type, a_field, (r_node)) != NULL; \
|
||||||
(r_node) = rbtn_left_get(a_type, a_field, (r_node))) { \
|
(r_node) = rbtn_left_get(a_type, a_field, (r_node))) { \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
@ -137,10 +134,9 @@ struct { \
|
|||||||
|
|
||||||
#define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \
|
#define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \
|
||||||
(r_node) = (a_root); \
|
(r_node) = (a_root); \
|
||||||
if ((r_node) != &(a_rbt)->rbt_nil) { \
|
if ((r_node) != NULL) { \
|
||||||
for (; rbtn_right_get(a_type, a_field, (r_node)) != \
|
for (; rbtn_right_get(a_type, a_field, (r_node)) != NULL; \
|
||||||
&(a_rbt)->rbt_nil; (r_node) = rbtn_right_get(a_type, a_field, \
|
(r_node) = rbtn_right_get(a_type, a_field, (r_node))) { \
|
||||||
(r_node))) { \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -335,8 +331,8 @@ a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \
|
|||||||
* Args:
|
* Args:
|
||||||
* tree: Pointer to an initialized red-black tree object.
|
* tree: Pointer to an initialized red-black tree object.
|
||||||
* cb : Callback function, which, if non-null, is called for each node
|
* cb : Callback function, which, if non-null, is called for each node
|
||||||
* during iteration. There is no way to stop iteration once it has
|
* during iteration. There is no way to stop iteration once it
|
||||||
* begun.
|
* has begun.
|
||||||
* arg : Opaque pointer passed to cb().
|
* arg : Opaque pointer passed to cb().
|
||||||
*/
|
*/
|
||||||
#define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \
|
#define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \
|
||||||
@ -346,36 +342,30 @@ a_prefix##new(a_rbt_type *rbtree) { \
|
|||||||
} \
|
} \
|
||||||
a_attr bool \
|
a_attr bool \
|
||||||
a_prefix##empty(a_rbt_type *rbtree) { \
|
a_prefix##empty(a_rbt_type *rbtree) { \
|
||||||
return (rbtree->rbt_root == &rbtree->rbt_nil); \
|
return (rbtree->rbt_root == NULL); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##first(a_rbt_type *rbtree) { \
|
a_prefix##first(a_rbt_type *rbtree) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
|
rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = NULL; \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##last(a_rbt_type *rbtree) { \
|
a_prefix##last(a_rbt_type *rbtree) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
|
rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret); \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = NULL; \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##next(a_rbt_type *rbtree, a_type *node) { \
|
a_prefix##next(a_rbt_type *rbtree, a_type *node) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
if (rbtn_right_get(a_type, a_field, node) != &rbtree->rbt_nil) { \
|
if (rbtn_right_get(a_type, a_field, node) != NULL) { \
|
||||||
rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type, \
|
rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type, \
|
||||||
a_field, node), ret); \
|
a_field, node), ret); \
|
||||||
} else { \
|
} else { \
|
||||||
a_type *tnode = rbtree->rbt_root; \
|
a_type *tnode = rbtree->rbt_root; \
|
||||||
assert(tnode != &rbtree->rbt_nil); \
|
assert(tnode != NULL); \
|
||||||
ret = &rbtree->rbt_nil; \
|
ret = NULL; \
|
||||||
while (true) { \
|
while (true) { \
|
||||||
int cmp = (a_cmp)(node, tnode); \
|
int cmp = (a_cmp)(node, tnode); \
|
||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
@ -386,24 +376,21 @@ a_prefix##next(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
} else { \
|
} else { \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
assert(tnode != &rbtree->rbt_nil); \
|
assert(tnode != NULL); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = (NULL); \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \
|
a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
if (rbtn_left_get(a_type, a_field, node) != &rbtree->rbt_nil) { \
|
if (rbtn_left_get(a_type, a_field, node) != NULL) { \
|
||||||
rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type, \
|
rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type, \
|
||||||
a_field, node), ret); \
|
a_field, node), ret); \
|
||||||
} else { \
|
} else { \
|
||||||
a_type *tnode = rbtree->rbt_root; \
|
a_type *tnode = rbtree->rbt_root; \
|
||||||
assert(tnode != &rbtree->rbt_nil); \
|
assert(tnode != NULL); \
|
||||||
ret = &rbtree->rbt_nil; \
|
ret = NULL; \
|
||||||
while (true) { \
|
while (true) { \
|
||||||
int cmp = (a_cmp)(node, tnode); \
|
int cmp = (a_cmp)(node, tnode); \
|
||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
@ -414,12 +401,9 @@ a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
} else { \
|
} else { \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
assert(tnode != &rbtree->rbt_nil); \
|
assert(tnode != NULL); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = (NULL); \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
@ -427,7 +411,7 @@ a_prefix##search(a_rbt_type *rbtree, const a_type *key) { \
|
|||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
int cmp; \
|
int cmp; \
|
||||||
ret = rbtree->rbt_root; \
|
ret = rbtree->rbt_root; \
|
||||||
while (ret != &rbtree->rbt_nil \
|
while (ret != NULL \
|
||||||
&& (cmp = (a_cmp)(key, ret)) != 0) { \
|
&& (cmp = (a_cmp)(key, ret)) != 0) { \
|
||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
ret = rbtn_left_get(a_type, a_field, ret); \
|
ret = rbtn_left_get(a_type, a_field, ret); \
|
||||||
@ -435,17 +419,14 @@ a_prefix##search(a_rbt_type *rbtree, const a_type *key) { \
|
|||||||
ret = rbtn_right_get(a_type, a_field, ret); \
|
ret = rbtn_right_get(a_type, a_field, ret); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = (NULL); \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) { \
|
a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
a_type *tnode = rbtree->rbt_root; \
|
a_type *tnode = rbtree->rbt_root; \
|
||||||
ret = &rbtree->rbt_nil; \
|
ret = NULL; \
|
||||||
while (tnode != &rbtree->rbt_nil) { \
|
while (tnode != NULL) { \
|
||||||
int cmp = (a_cmp)(key, tnode); \
|
int cmp = (a_cmp)(key, tnode); \
|
||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
ret = tnode; \
|
ret = tnode; \
|
||||||
@ -457,17 +438,14 @@ a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) { \
|
|||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = (NULL); \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) { \
|
a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
a_type *tnode = rbtree->rbt_root; \
|
a_type *tnode = rbtree->rbt_root; \
|
||||||
ret = &rbtree->rbt_nil; \
|
ret = NULL; \
|
||||||
while (tnode != &rbtree->rbt_nil) { \
|
while (tnode != NULL) { \
|
||||||
int cmp = (a_cmp)(key, tnode); \
|
int cmp = (a_cmp)(key, tnode); \
|
||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
tnode = rbtn_left_get(a_type, a_field, tnode); \
|
tnode = rbtn_left_get(a_type, a_field, tnode); \
|
||||||
@ -479,9 +457,6 @@ a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) { \
|
|||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = (NULL); \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr void \
|
a_attr void \
|
||||||
@ -493,7 +468,7 @@ a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
rbt_node_new(a_type, a_field, rbtree, node); \
|
rbt_node_new(a_type, a_field, rbtree, node); \
|
||||||
/* Wind. */ \
|
/* Wind. */ \
|
||||||
path->node = rbtree->rbt_root; \
|
path->node = rbtree->rbt_root; \
|
||||||
for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \
|
for (pathp = path; pathp->node != NULL; pathp++) { \
|
||||||
int cmp = pathp->cmp = a_cmp(node, pathp->node); \
|
int cmp = pathp->cmp = a_cmp(node, pathp->node); \
|
||||||
assert(cmp != 0); \
|
assert(cmp != 0); \
|
||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
@ -513,7 +488,8 @@ a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
rbtn_left_set(a_type, a_field, cnode, left); \
|
rbtn_left_set(a_type, a_field, cnode, left); \
|
||||||
if (rbtn_red_get(a_type, a_field, left)) { \
|
if (rbtn_red_get(a_type, a_field, left)) { \
|
||||||
a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
|
a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
|
||||||
if (rbtn_red_get(a_type, a_field, leftleft)) { \
|
if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
|
||||||
|
leftleft)) { \
|
||||||
/* Fix up 4-node. */ \
|
/* Fix up 4-node. */ \
|
||||||
a_type *tnode; \
|
a_type *tnode; \
|
||||||
rbtn_black_set(a_type, a_field, leftleft); \
|
rbtn_black_set(a_type, a_field, leftleft); \
|
||||||
@ -528,7 +504,8 @@ a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
rbtn_right_set(a_type, a_field, cnode, right); \
|
rbtn_right_set(a_type, a_field, cnode, right); \
|
||||||
if (rbtn_red_get(a_type, a_field, right)) { \
|
if (rbtn_red_get(a_type, a_field, right)) { \
|
||||||
a_type *left = rbtn_left_get(a_type, a_field, cnode); \
|
a_type *left = rbtn_left_get(a_type, a_field, cnode); \
|
||||||
if (rbtn_red_get(a_type, a_field, left)) { \
|
if (left != NULL && rbtn_red_get(a_type, a_field, \
|
||||||
|
left)) { \
|
||||||
/* Split 4-node. */ \
|
/* Split 4-node. */ \
|
||||||
rbtn_black_set(a_type, a_field, left); \
|
rbtn_black_set(a_type, a_field, left); \
|
||||||
rbtn_black_set(a_type, a_field, right); \
|
rbtn_black_set(a_type, a_field, right); \
|
||||||
@ -561,7 +538,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
/* Wind. */ \
|
/* Wind. */ \
|
||||||
nodep = NULL; /* Silence compiler warning. */ \
|
nodep = NULL; /* Silence compiler warning. */ \
|
||||||
path->node = rbtree->rbt_root; \
|
path->node = rbtree->rbt_root; \
|
||||||
for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \
|
for (pathp = path; pathp->node != NULL; pathp++) { \
|
||||||
int cmp = pathp->cmp = a_cmp(node, pathp->node); \
|
int cmp = pathp->cmp = a_cmp(node, pathp->node); \
|
||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
pathp[1].node = rbtn_left_get(a_type, a_field, \
|
pathp[1].node = rbtn_left_get(a_type, a_field, \
|
||||||
@ -573,7 +550,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
/* Find node's successor, in preparation for swap. */ \
|
/* Find node's successor, in preparation for swap. */ \
|
||||||
pathp->cmp = 1; \
|
pathp->cmp = 1; \
|
||||||
nodep = pathp; \
|
nodep = pathp; \
|
||||||
for (pathp++; pathp->node != &rbtree->rbt_nil; \
|
for (pathp++; pathp->node != NULL; \
|
||||||
pathp++) { \
|
pathp++) { \
|
||||||
pathp->cmp = -1; \
|
pathp->cmp = -1; \
|
||||||
pathp[1].node = rbtn_left_get(a_type, a_field, \
|
pathp[1].node = rbtn_left_get(a_type, a_field, \
|
||||||
@ -616,7 +593,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
a_type *left = rbtn_left_get(a_type, a_field, node); \
|
a_type *left = rbtn_left_get(a_type, a_field, node); \
|
||||||
if (left != &rbtree->rbt_nil) { \
|
if (left != NULL) { \
|
||||||
/* node has no successor, but it has a left child. */\
|
/* node has no successor, but it has a left child. */\
|
||||||
/* Splice node out, without losing the left child. */\
|
/* Splice node out, without losing the left child. */\
|
||||||
assert(!rbtn_red_get(a_type, a_field, node)); \
|
assert(!rbtn_red_get(a_type, a_field, node)); \
|
||||||
@ -636,33 +613,32 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
return; \
|
return; \
|
||||||
} else if (pathp == path) { \
|
} else if (pathp == path) { \
|
||||||
/* The tree only contained one node. */ \
|
/* The tree only contained one node. */ \
|
||||||
rbtree->rbt_root = &rbtree->rbt_nil; \
|
rbtree->rbt_root = NULL; \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
if (rbtn_red_get(a_type, a_field, pathp->node)) { \
|
if (rbtn_red_get(a_type, a_field, pathp->node)) { \
|
||||||
/* Prune red node, which requires no fixup. */ \
|
/* Prune red node, which requires no fixup. */ \
|
||||||
assert(pathp[-1].cmp < 0); \
|
assert(pathp[-1].cmp < 0); \
|
||||||
rbtn_left_set(a_type, a_field, pathp[-1].node, \
|
rbtn_left_set(a_type, a_field, pathp[-1].node, NULL); \
|
||||||
&rbtree->rbt_nil); \
|
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
/* The node to be pruned is black, so unwind until balance is */\
|
/* The node to be pruned is black, so unwind until balance is */\
|
||||||
/* restored. */\
|
/* restored. */\
|
||||||
pathp->node = &rbtree->rbt_nil; \
|
pathp->node = NULL; \
|
||||||
for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
|
for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \
|
||||||
assert(pathp->cmp != 0); \
|
assert(pathp->cmp != 0); \
|
||||||
if (pathp->cmp < 0) { \
|
if (pathp->cmp < 0) { \
|
||||||
rbtn_left_set(a_type, a_field, pathp->node, \
|
rbtn_left_set(a_type, a_field, pathp->node, \
|
||||||
pathp[1].node); \
|
pathp[1].node); \
|
||||||
assert(!rbtn_red_get(a_type, a_field, pathp[1].node)); \
|
|
||||||
if (rbtn_red_get(a_type, a_field, pathp->node)) { \
|
if (rbtn_red_get(a_type, a_field, pathp->node)) { \
|
||||||
a_type *right = rbtn_right_get(a_type, a_field, \
|
a_type *right = rbtn_right_get(a_type, a_field, \
|
||||||
pathp->node); \
|
pathp->node); \
|
||||||
a_type *rightleft = rbtn_left_get(a_type, a_field, \
|
a_type *rightleft = rbtn_left_get(a_type, a_field, \
|
||||||
right); \
|
right); \
|
||||||
a_type *tnode; \
|
a_type *tnode; \
|
||||||
if (rbtn_red_get(a_type, a_field, rightleft)) { \
|
if (rightleft != NULL && rbtn_red_get(a_type, a_field, \
|
||||||
|
rightleft)) { \
|
||||||
/* In the following diagrams, ||, //, and \\ */\
|
/* In the following diagrams, ||, //, and \\ */\
|
||||||
/* indicate the path to the removed node. */\
|
/* indicate the path to the removed node. */\
|
||||||
/* */\
|
/* */\
|
||||||
@ -705,7 +681,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
pathp->node); \
|
pathp->node); \
|
||||||
a_type *rightleft = rbtn_left_get(a_type, a_field, \
|
a_type *rightleft = rbtn_left_get(a_type, a_field, \
|
||||||
right); \
|
right); \
|
||||||
if (rbtn_red_get(a_type, a_field, rightleft)) { \
|
if (rightleft != NULL && rbtn_red_get(a_type, a_field, \
|
||||||
|
rightleft)) { \
|
||||||
/* || */\
|
/* || */\
|
||||||
/* pathp(b) */\
|
/* pathp(b) */\
|
||||||
/* // \ */\
|
/* // \ */\
|
||||||
@ -759,7 +736,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
left); \
|
left); \
|
||||||
a_type *leftrightleft = rbtn_left_get(a_type, a_field, \
|
a_type *leftrightleft = rbtn_left_get(a_type, a_field, \
|
||||||
leftright); \
|
leftright); \
|
||||||
if (rbtn_red_get(a_type, a_field, leftrightleft)) { \
|
if (leftrightleft != NULL && rbtn_red_get(a_type, \
|
||||||
|
a_field, leftrightleft)) { \
|
||||||
/* || */\
|
/* || */\
|
||||||
/* pathp(b) */\
|
/* pathp(b) */\
|
||||||
/* / \\ */\
|
/* / \\ */\
|
||||||
@ -785,7 +763,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
/* (b) */\
|
/* (b) */\
|
||||||
/* / */\
|
/* / */\
|
||||||
/* (b) */\
|
/* (b) */\
|
||||||
assert(leftright != &rbtree->rbt_nil); \
|
assert(leftright != NULL); \
|
||||||
rbtn_red_set(a_type, a_field, leftright); \
|
rbtn_red_set(a_type, a_field, leftright); \
|
||||||
rbtn_rotate_right(a_type, a_field, pathp->node, \
|
rbtn_rotate_right(a_type, a_field, pathp->node, \
|
||||||
tnode); \
|
tnode); \
|
||||||
@ -808,7 +786,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
return; \
|
return; \
|
||||||
} else if (rbtn_red_get(a_type, a_field, pathp->node)) { \
|
} else if (rbtn_red_get(a_type, a_field, pathp->node)) { \
|
||||||
a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
|
a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
|
||||||
if (rbtn_red_get(a_type, a_field, leftleft)) { \
|
if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
|
||||||
|
leftleft)) { \
|
||||||
/* || */\
|
/* || */\
|
||||||
/* pathp(r) */\
|
/* pathp(r) */\
|
||||||
/* / \\ */\
|
/* / \\ */\
|
||||||
@ -846,7 +825,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
|
a_type *leftleft = rbtn_left_get(a_type, a_field, left);\
|
||||||
if (rbtn_red_get(a_type, a_field, leftleft)) { \
|
if (leftleft != NULL && rbtn_red_get(a_type, a_field, \
|
||||||
|
leftleft)) { \
|
||||||
/* || */\
|
/* || */\
|
||||||
/* pathp(b) */\
|
/* pathp(b) */\
|
||||||
/* / \\ */\
|
/* / \\ */\
|
||||||
@ -892,13 +872,13 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \
|
|||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node, \
|
a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node, \
|
||||||
a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
|
a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
|
||||||
if (node == &rbtree->rbt_nil) { \
|
if (node == NULL) { \
|
||||||
return (&rbtree->rbt_nil); \
|
return (NULL); \
|
||||||
} else { \
|
} else { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type, \
|
if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type, \
|
||||||
a_field, node), cb, arg)) != &rbtree->rbt_nil \
|
a_field, node), cb, arg)) != NULL || (ret = cb(rbtree, node, \
|
||||||
|| (ret = cb(rbtree, node, arg)) != NULL) { \
|
arg)) != NULL) { \
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
|
return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
|
||||||
@ -912,8 +892,8 @@ a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node, \
|
|||||||
if (cmp < 0) { \
|
if (cmp < 0) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
if ((ret = a_prefix##iter_start(rbtree, start, \
|
if ((ret = a_prefix##iter_start(rbtree, start, \
|
||||||
rbtn_left_get(a_type, a_field, node), cb, arg)) != \
|
rbtn_left_get(a_type, a_field, node), cb, arg)) != NULL || \
|
||||||
&rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \
|
(ret = cb(rbtree, node, arg)) != NULL) { \
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
|
return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \
|
||||||
@ -940,21 +920,18 @@ a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \
|
|||||||
} else { \
|
} else { \
|
||||||
ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\
|
ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\
|
||||||
} \
|
} \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = NULL; \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr a_type * \
|
a_attr a_type * \
|
||||||
a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node, \
|
a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node, \
|
||||||
a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
|
a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \
|
||||||
if (node == &rbtree->rbt_nil) { \
|
if (node == NULL) { \
|
||||||
return (&rbtree->rbt_nil); \
|
return (NULL); \
|
||||||
} else { \
|
} else { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
if ((ret = a_prefix##reverse_iter_recurse(rbtree, \
|
if ((ret = a_prefix##reverse_iter_recurse(rbtree, \
|
||||||
rbtn_right_get(a_type, a_field, node), cb, arg)) != \
|
rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \
|
||||||
&rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \
|
(ret = cb(rbtree, node, arg)) != NULL) { \
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
return (a_prefix##reverse_iter_recurse(rbtree, \
|
return (a_prefix##reverse_iter_recurse(rbtree, \
|
||||||
@ -969,8 +946,8 @@ a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start, \
|
|||||||
if (cmp > 0) { \
|
if (cmp > 0) { \
|
||||||
a_type *ret; \
|
a_type *ret; \
|
||||||
if ((ret = a_prefix##reverse_iter_start(rbtree, start, \
|
if ((ret = a_prefix##reverse_iter_start(rbtree, start, \
|
||||||
rbtn_right_get(a_type, a_field, node), cb, arg)) != \
|
rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \
|
||||||
&rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \
|
(ret = cb(rbtree, node, arg)) != NULL) { \
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
return (a_prefix##reverse_iter_recurse(rbtree, \
|
return (a_prefix##reverse_iter_recurse(rbtree, \
|
||||||
@ -998,23 +975,20 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \
|
|||||||
ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root, \
|
ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root, \
|
||||||
cb, arg); \
|
cb, arg); \
|
||||||
} \
|
} \
|
||||||
if (ret == &rbtree->rbt_nil) { \
|
|
||||||
ret = NULL; \
|
|
||||||
} \
|
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
a_attr void \
|
a_attr void \
|
||||||
a_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)( \
|
a_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)( \
|
||||||
a_type *, void *), void *arg) { \
|
a_type *, void *), void *arg) { \
|
||||||
if (node == &rbtree->rbt_nil) { \
|
if (node == NULL) { \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field, \
|
a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field, \
|
||||||
node), cb, arg); \
|
node), cb, arg); \
|
||||||
rbtn_left_set(a_type, a_field, (node), &rbtree->rbt_nil); \
|
rbtn_left_set(a_type, a_field, (node), NULL); \
|
||||||
a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field, \
|
a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field, \
|
||||||
node), cb, arg); \
|
node), cb, arg); \
|
||||||
rbtn_right_set(a_type, a_field, (node), &rbtree->rbt_nil); \
|
rbtn_right_set(a_type, a_field, (node), NULL); \
|
||||||
if (cb) { \
|
if (cb) { \
|
||||||
cb(node, arg); \
|
cb(node, arg); \
|
||||||
} \
|
} \
|
||||||
@ -1023,7 +997,7 @@ a_attr void \
|
|||||||
a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \
|
a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \
|
||||||
void *arg) { \
|
void *arg) { \
|
||||||
a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg); \
|
a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg); \
|
||||||
rbtree->rbt_root = &rbtree->rbt_nil; \
|
rbtree->rbt_root = NULL; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* RB_H_ */
|
#endif /* RB_H_ */
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#define rbtn_black_height(a_type, a_field, a_rbt, r_height) do { \
|
#define rbtn_black_height(a_type, a_field, a_rbt, r_height) do { \
|
||||||
a_type *rbp_bh_t; \
|
a_type *rbp_bh_t; \
|
||||||
for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0; \
|
for (rbp_bh_t = (a_rbt)->rbt_root, (r_height) = 0; \
|
||||||
rbp_bh_t != &(a_rbt)->rbt_nil; \
|
rbp_bh_t != NULL; \
|
||||||
rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) { \
|
rbp_bh_t = rbtn_left_get(a_type, a_field, rbp_bh_t)) { \
|
||||||
if (!rbtn_red_get(a_type, a_field, rbp_bh_t)) { \
|
if (!rbtn_red_get(a_type, a_field, rbp_bh_t)) { \
|
||||||
(r_height)++; \
|
(r_height)++; \
|
||||||
@ -68,38 +68,43 @@ TEST_BEGIN(test_rb_empty)
|
|||||||
TEST_END
|
TEST_END
|
||||||
|
|
||||||
static unsigned
|
static unsigned
|
||||||
tree_recurse(node_t *node, unsigned black_height, unsigned black_depth,
|
tree_recurse(node_t *node, unsigned black_height, unsigned black_depth)
|
||||||
node_t *nil)
|
|
||||||
{
|
{
|
||||||
unsigned ret = 0;
|
unsigned ret = 0;
|
||||||
node_t *left_node = rbtn_left_get(node_t, link, node);
|
node_t *left_node;
|
||||||
node_t *right_node = rbtn_right_get(node_t, link, node);
|
node_t *right_node;
|
||||||
|
|
||||||
|
if (node == NULL)
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
left_node = rbtn_left_get(node_t, link, node);
|
||||||
|
right_node = rbtn_right_get(node_t, link, node);
|
||||||
|
|
||||||
if (!rbtn_red_get(node_t, link, node))
|
if (!rbtn_red_get(node_t, link, node))
|
||||||
black_depth++;
|
black_depth++;
|
||||||
|
|
||||||
/* Red nodes must be interleaved with black nodes. */
|
/* Red nodes must be interleaved with black nodes. */
|
||||||
if (rbtn_red_get(node_t, link, node)) {
|
if (rbtn_red_get(node_t, link, node)) {
|
||||||
|
if (left_node != NULL)
|
||||||
assert_false(rbtn_red_get(node_t, link, left_node),
|
assert_false(rbtn_red_get(node_t, link, left_node),
|
||||||
"Node should be black");
|
"Node should be black");
|
||||||
|
if (right_node != NULL)
|
||||||
assert_false(rbtn_red_get(node_t, link, right_node),
|
assert_false(rbtn_red_get(node_t, link, right_node),
|
||||||
"Node should be black");
|
"Node should be black");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node == nil)
|
|
||||||
return (ret);
|
|
||||||
/* Self. */
|
/* Self. */
|
||||||
assert_u32_eq(node->magic, NODE_MAGIC, "Bad magic");
|
assert_u32_eq(node->magic, NODE_MAGIC, "Bad magic");
|
||||||
|
|
||||||
/* Left subtree. */
|
/* Left subtree. */
|
||||||
if (left_node != nil)
|
if (left_node != NULL)
|
||||||
ret += tree_recurse(left_node, black_height, black_depth, nil);
|
ret += tree_recurse(left_node, black_height, black_depth);
|
||||||
else
|
else
|
||||||
ret += (black_depth != black_height);
|
ret += (black_depth != black_height);
|
||||||
|
|
||||||
/* Right subtree. */
|
/* Right subtree. */
|
||||||
if (right_node != nil)
|
if (right_node != NULL)
|
||||||
ret += tree_recurse(right_node, black_height, black_depth, nil);
|
ret += tree_recurse(right_node, black_height, black_depth);
|
||||||
else
|
else
|
||||||
ret += (black_depth != black_height);
|
ret += (black_depth != black_height);
|
||||||
|
|
||||||
@ -181,8 +186,7 @@ node_remove(tree_t *tree, node_t *node, unsigned nnodes)
|
|||||||
node->magic = 0;
|
node->magic = 0;
|
||||||
|
|
||||||
rbtn_black_height(node_t, link, tree, black_height);
|
rbtn_black_height(node_t, link, tree, black_height);
|
||||||
imbalances = tree_recurse(tree->rbt_root, black_height, 0,
|
imbalances = tree_recurse(tree->rbt_root, black_height, 0);
|
||||||
&(tree->rbt_nil));
|
|
||||||
assert_u_eq(imbalances, 0, "Tree is unbalanced");
|
assert_u_eq(imbalances, 0, "Tree is unbalanced");
|
||||||
assert_u_eq(tree_iterate(tree), nnodes-1,
|
assert_u_eq(tree_iterate(tree), nnodes-1,
|
||||||
"Unexpected node iteration count");
|
"Unexpected node iteration count");
|
||||||
@ -253,7 +257,6 @@ TEST_BEGIN(test_rb_random)
|
|||||||
for (j = 1; j <= NNODES; j++) {
|
for (j = 1; j <= NNODES; j++) {
|
||||||
/* Initialize tree and nodes. */
|
/* Initialize tree and nodes. */
|
||||||
tree_new(&tree);
|
tree_new(&tree);
|
||||||
tree.rbt_nil.magic = 0;
|
|
||||||
for (k = 0; k < j; k++) {
|
for (k = 0; k < j; k++) {
|
||||||
nodes[k].magic = NODE_MAGIC;
|
nodes[k].magic = NODE_MAGIC;
|
||||||
nodes[k].key = bag[k];
|
nodes[k].key = bag[k];
|
||||||
@ -266,7 +269,7 @@ TEST_BEGIN(test_rb_random)
|
|||||||
rbtn_black_height(node_t, link, &tree,
|
rbtn_black_height(node_t, link, &tree,
|
||||||
black_height);
|
black_height);
|
||||||
imbalances = tree_recurse(tree.rbt_root,
|
imbalances = tree_recurse(tree.rbt_root,
|
||||||
black_height, 0, &(tree.rbt_nil));
|
black_height, 0);
|
||||||
assert_u_eq(imbalances, 0,
|
assert_u_eq(imbalances, 0,
|
||||||
"Tree is unbalanced");
|
"Tree is unbalanced");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user