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