Add rbtree iterator implementation
This commit is contained in:
parent
8858e02afb
commit
4a174df6da
@ -64,6 +64,17 @@ extern int libcdsb_builtin_vtype_compare_values (const void* s0, vtype t0,
|
||||
extern int libcdsb_builtin_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) pure__ wur__;
|
||||
extern hash_t libcdsb_builtin_vtype_hash (const void* value, vtype type) pure__ wur__;
|
||||
|
||||
ainline(stack_t* libcdsb_builtin_stack_insert(stack_t* x, void* v)) {
|
||||
stack_t* p = x->prev;
|
||||
|
||||
if (!is_null(x->prev = malloc(sizeof(*x)))) {
|
||||
x->prev->prev = p;
|
||||
x->prev->value = v;
|
||||
} else abort();
|
||||
|
||||
return x->prev;
|
||||
}
|
||||
|
||||
#define aligned_alloc libcdsb_aalloc
|
||||
#define malloc libcdsb_malloc
|
||||
#define calloc libcdsb_calloc
|
||||
@ -72,7 +83,9 @@ extern hash_t libcdsb_builtin_vtype_hash (const void* value, vtype t
|
||||
#define stack_init libcdsb_stack_init
|
||||
#define stack_push libcdsb_stack_push
|
||||
#define stack_push_many libcdsb_stack_push_many
|
||||
#define stack_insert libcdsb_builtin_stack_insert
|
||||
#define stack_pop libcdsb_stack_pop
|
||||
#define stack_reverse libcdsb_stack_reverse
|
||||
#define stack_flush libcdsb_stack_flush
|
||||
#define strlen libcdsb_strlen
|
||||
#define strasciilen libcdsb_strasciilen
|
||||
|
@ -21,9 +21,10 @@ extern void* libcdsb_builtin_rbtree_node_create(void* value, rbnode_t* paren
|
||||
extern void libcdsb_builtin_rbtree_node_fixup (rbnode_t** root, rbnode_t* node) Nonnull__(1,2);
|
||||
extern rbnode_t* libcdsb_builtin_rbtree_node_delete(rbnode_t** root, rbnode_t* node) Nonnull__(1,2);
|
||||
|
||||
extern rbnode_t* libcdsb_builtin_rbtree_next_inorder (rbnode_t** root, rbnode_t* prev, bool reverse);
|
||||
extern rbnode_t* libcdsb_builtin_rbtree_next_preorder (rbnode_t** root, rbnode_t* prev, bool reverse);
|
||||
extern rbnode_t* libcdsb_builtin_rbtree_next_postorder(rbnode_t** root, rbnode_t* prev, bool reverse);
|
||||
extern stack_t libcdsb_builtin_rbtree_iter_inorder (rbnode_t** root, bool reverse);
|
||||
extern stack_t libcdsb_builtin_rbtree_iter_preorder (rbnode_t** root, bool reverse);
|
||||
extern stack_t libcdsb_builtin_rbtree_iter_postorder (rbnode_t** root, bool reverse);
|
||||
extern stack_t libcdsb_builtin_rbtree_iter_breath_first(rbnode_t** root, bool reverse);
|
||||
|
||||
#define rbnode_empty ((rbnode_t*)LIBCDSB_BUILTIN_RBTREE_NODE_EMPTY)
|
||||
#define rbnode_create(v, p, c) ((rbnode_t*)libcdsb_builtin_rbtree_node_create(v, p, c, sizeof(rbnode_t)))
|
||||
@ -33,4 +34,9 @@ extern rbnode_t* libcdsb_builtin_rbtree_next_postorder(rbnode_t** root, rbnode_t
|
||||
#define rbnode_is_empty(n) ((n) == rbnode_empty)
|
||||
#define rbnode_is_root(n) rbnode_is_empty((n)->parent)
|
||||
|
||||
#define rbiter_inorder libcdsb_builtin_rbtree_iter_inorder
|
||||
#define rbiter_preorder libcdsb_builtin_rbtree_iter_preorder
|
||||
#define rbiter_postorder libcdsb_builtin_rbtree_iter_postorder
|
||||
#define rbiter_breath_first libcdsb_builtin_rbtree_iter_breath_first
|
||||
|
||||
#endif /* LIBCDSB_SRC_INTERNAL_RBTREE_H */
|
||||
|
157
src/rbtree.c
157
src/rbtree.c
@ -193,3 +193,160 @@ void* libcdsb_builtin_rbtree_node_create(void* v, rbnode_t* p, int c, int n) {
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
stack_t libcdsb_builtin_rbtree_iter_inorder(rbnode_t** root, bool reverse) {
|
||||
rbnode_t *n, hack;
|
||||
stack_t z, *bot;
|
||||
|
||||
memset(&z, 0, sizeof(z));
|
||||
|
||||
if (rbnode_is_empty(*root))
|
||||
return z;
|
||||
|
||||
hack.right = *root;
|
||||
n = &hack;
|
||||
|
||||
for (bot = &z;;) {
|
||||
for (;;) {
|
||||
if (rbnode_is_empty(n->right)) {
|
||||
|
||||
if (rbnode_is_root(n->parent) || n->parent->left == n) {
|
||||
n = n->parent;
|
||||
break;
|
||||
} else n = n->parent;
|
||||
|
||||
if (rbnode_is_root(n->parent) || n->parent->left == n) {
|
||||
n = n->parent;
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
n = n->parent;
|
||||
} while (n->parent->right == n);
|
||||
|
||||
n = n->parent;
|
||||
} else {
|
||||
n = n->right;
|
||||
|
||||
while (!rbnode_is_empty(n->left))
|
||||
n = n->left;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (rbnode_is_root(n)) {
|
||||
bot = z.prev;
|
||||
z = *bot;
|
||||
|
||||
free(bot);
|
||||
|
||||
if (reverse)
|
||||
stack_reverse(&z);
|
||||
|
||||
return z;
|
||||
}
|
||||
}
|
||||
|
||||
bot = stack_insert(bot, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stack_t libcdsb_builtin_rbtree_iter_preorder(rbnode_t** root, bool reverse) {
|
||||
stack_t z, *cur, *next;
|
||||
rbnode_t *n;
|
||||
|
||||
memset(&z, 0, sizeof(z));
|
||||
|
||||
if (rbnode_is_empty(*root))
|
||||
return z;
|
||||
|
||||
z.value = *root;
|
||||
cur = &z;
|
||||
|
||||
do {
|
||||
n = (next = cur)->value;
|
||||
|
||||
if (!rbnode_is_empty(n->left)) next = stack_insert(cur, n->left);
|
||||
if (!rbnode_is_empty(n->right)) stack_insert(next, n->right);
|
||||
} while (!is_null(cur = cur->prev));
|
||||
|
||||
if (reverse)
|
||||
stack_reverse(&z);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
stack_t libcdsb_builtin_rbtree_iter_postorder(rbnode_t** root, bool reverse) {
|
||||
rbnode_t *p, *n;
|
||||
stack_t z, *bot;
|
||||
|
||||
bot = &z;
|
||||
z.prev = 0;
|
||||
z.value = 0;
|
||||
|
||||
if (rbnode_is_empty(p = *root))
|
||||
return z;
|
||||
|
||||
goto mid_;
|
||||
|
||||
do {
|
||||
if (n->parent->right != n && !rbnode_is_empty(n->parent->right)) {
|
||||
p = n->parent->right;
|
||||
do { mid_:
|
||||
n = p;
|
||||
p = !rbnode_is_empty(p->left) ? p->left : p->right;
|
||||
} while (!rbnode_is_empty(p));
|
||||
} else n = n->parent;
|
||||
|
||||
bot = stack_insert(bot, n);
|
||||
} while (!rbnode_is_root(n));
|
||||
|
||||
bot = z.prev;
|
||||
z = *bot;
|
||||
|
||||
free(bot);
|
||||
|
||||
if (reverse)
|
||||
stack_reverse(&z);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
stack_t libcdsb_builtin_rbtree_iter_breath_first(rbnode_t** root, bool reverse) {
|
||||
|
||||
stack_t z, *top, *bot, *cur;
|
||||
rbnode_t* n;
|
||||
|
||||
memset(&z, 0, sizeof(z));
|
||||
|
||||
if (rbnode_is_empty(z.value = *root))
|
||||
return z;
|
||||
|
||||
for (top = bot = &z;;) {
|
||||
for (cur = bot;;) {
|
||||
|
||||
n = top->value;
|
||||
|
||||
if (!rbnode_is_empty(n->left)) cur = stack_insert(cur, n->left);
|
||||
if (!rbnode_is_empty(n->right)) cur = stack_insert(cur, n->right);
|
||||
|
||||
if (top == bot) {
|
||||
top = top->prev;
|
||||
break;
|
||||
} else top = top->prev;
|
||||
}
|
||||
|
||||
if (!is_null(top)) {
|
||||
while (!is_null(bot->prev)) bot = bot->prev;
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
stack_reverse(&z);
|
||||
|
||||
return z;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user