From e94cdc978388debfbe183d226fc7daf5617390b9 Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Tue, 7 Jun 2022 21:34:30 +0300 Subject: [PATCH] Clean the rbtree implementation --- src/__internal/rbtree.h | 23 +---- src/rbtree.c | 194 ++-------------------------------------- 2 files changed, 7 insertions(+), 210 deletions(-) diff --git a/src/__internal/rbtree.h b/src/__internal/rbtree.h index 33d4fb5..79edf6b 100644 --- a/src/__internal/rbtree.h +++ b/src/__internal/rbtree.h @@ -6,14 +6,6 @@ #ifndef LIBCDSB_SRC_INTERNAL_RBTREE_H #define LIBCDSB_SRC_INTERNAL_RBTREE_H -typedef enum libcdsb_rbtree_iter_flags { - RBI_INORDER = 0, - RBI_PREORDER = 1, - RBI_POSTORDER = 2, - - RBI_REVERSE = 4, -} rbiter_f; - typedef struct libcdsb_rbtree_node { struct libcdsb_rbtree_node* left; struct libcdsb_rbtree_node* right; @@ -23,30 +15,17 @@ typedef struct libcdsb_rbtree_node { short colored; } rbnode_t; -typedef struct libcdsb_rbtree_iter { - struct libcdsb_rbtree_node* cursor; - int flags; -} rbiter_t; - -extern const rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1]; +extern rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1]; extern void* libcdsb_rbtree_node_create(void* value, rbnode_t* parent, int colored, int size); extern void libcdsb_rbtree_node_fixup (rbnode_t** root, rbnode_t* node); extern rbnode_t* libcdsb_rbtree_node_delete(rbnode_t** root, rbnode_t* node); -extern _Bool libcdsb_rbtree_iter_init (rbiter_t* iter, rbnode_t *const *root, rbiter_f flags); -extern rbnode_t* libcdsb_rbtree_iter_next (rbiter_t* iter); -extern void libcdsb_rbtree_iter_reset(rbiter_t* iter); - #define rbnode_empty ((rbnode_t*)LIBCDSB_RBTREE_NODE_EMPTY) #define rbnode_create(v, p, c) ((rbnode_t*)libcdsb_rbtree_node_create(v, p, c, sizeof(rbnode_t))) #define rbnode_fixup libcdsb_rbtree_node_fixup #define rbnode_delete libcdsb_rbtree_node_delete -#define rbiter_init libcdsb_rbtree_iter_init -#define rbiter_next libcdsb_rbtree_iter_next -#define rbiter_reset libcdsb_rbtree_iter_reset - #define rbnode_is_empty(n) ((n) == rbnode_empty) #define rbnode_is_root(n) rbnode_is_empty((n)->parent) diff --git a/src/rbtree.c b/src/rbtree.c index a8681b7..9c7d328 100644 --- a/src/rbtree.c +++ b/src/rbtree.c @@ -3,9 +3,6 @@ #include "__internal/rbtree.h" -#define RBI_BREAK ((rbiter_f)3) -#define RBI_FIRST ((rbiter_f)8) - typedef enum libcdsb_rbtree_node_direction { RBD_LEFT = 1, RBD_RIGHT = 2 @@ -16,7 +13,7 @@ typedef enum libcdsb_rbtree_node_direction { /*#####################################################################################################################*/ -const rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1] = {{ +rbnode_t LIBCDSB_RBTREE_NODE_EMPTY[1] = {{ .colored = 0, .value = 0, .parent = rbnode_empty, @@ -45,105 +42,12 @@ static inline void rotate(rbnode_t **x, rbnode_t *c, rbdir_t d) { } static inline void replace(rbnode_t** x, rbnode_t* c, rbnode_t* n) { - rbnode_t* p; - - p = c->parent; - - if (!rbnode_is_empty(p)) { - if (p->left == c) { - p->left = n; - } else p->right = n; + if (!rbnode_is_root(c)) { + if (c->parent->left == c) { + c->parent->left = n; + } else c->parent->right = n; } else *x = n; - - n->parent = p; -} - - -/*#####################################################################################################################*/ - - -static rbnode_t* inorder_next(rbnode_t* c, rbiter_f f) { - rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT; - rbnode_t* p; - - for (;;) { - if (rbnode_is_empty(rbdir_inv(c, d))) { - p = c->parent; - - if (rbnode_is_root(p) || rbdir_dir(p, d) == c) { - return p; - } - - c = p; - p = c->parent; - - if (rbnode_is_root(p) || rbdir_dir(p, d) == c) { - return p; - } - - do { - c = p; - p = c->parent; - } while(rbdir_inv(p, d) == c); - - c = p; - - } else { c = rbdir_inv(c, d); break; } - - if (rbnode_is_root(c)) return c; - } - - while (!rbnode_is_empty(rbdir_dir(c, d))) - c = rbdir_dir(c, d); - - return c; -} - -static rbnode_t* postorder_next(rbnode_t* c, rbiter_f f) { - rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT; - rbnode_t* p; - - if (rbnode_is_empty(p = c->parent)) - return c; - - if (rbdir_dir(p, d) == c && !rbnode_is_empty(rbdir_inv(p, d))) { - c = rbdir_inv(p, d); - - while (!rbnode_is_empty(c)) { - p = c; - c = (!rbnode_is_empty(rbdir_inv(p, d))) - ? rbdir_inv(p, d) - : rbdir_dir(p, d); - } - } - - return p; -} - -static rbnode_t* preorder_next(rbnode_t* c, rbiter_f f) { - rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT; - rbnode_t* p; - - if (!rbnode_is_empty(rbdir_dir(c, d))) - return rbdir_dir(c, d); - - for (;;) { - if (!rbnode_is_empty(rbdir_inv(c, d))) { - return rbdir_inv(c, d); - } - - p = c->parent; - - while (rbdir_inv(p, d) == c) { - c = p; - p = c->parent; - } - - if (rbnode_is_empty(p)) - return c; - - c = p; - } + n->parent = c->parent; } @@ -290,89 +194,3 @@ void* libcdsb_rbtree_node_create(void* v, rbnode_t* p, int c, int n) { return x; } - - -/*#####################################################################################################################*/ - - -_Bool libcdsb_rbtree_iter_init(rbiter_t* iter, rbnode_t *const *root, rbiter_f f) { - rbdir_t d = (f&RBI_REVERSE) ? RBD_RIGHT : RBD_LEFT; - rbnode_t* c = *root; - - if (!rbnode_is_empty(c)) { - if (!(f&RBI_BREAK)) { - while (rbdir_dir(c, d) != rbnode_empty) { - c = rbdir_dir(c, d); - } - } else if ((f&RBI_BREAK) == RBI_POSTORDER) { - rbnode_t* p; - - do { - p = c; - c = (!rbnode_is_empty(rbdir_dir(c, d))) ? rbdir_dir(c, d) : rbdir_inv(c, d); - } while (!rbnode_is_empty(c)); - - c = p; - } - } else { - iter->cursor = rbnode_empty; - iter->flags = 0; - return false; - } - - iter->cursor = c; - iter->flags = f|RBI_FIRST; - - return true; -} - - - -void libcdsb_rbtree_iter_reset(rbiter_t* iter) { - if (iter->flags&RBI_FIRST) return; - - while (!rbnode_is_empty(iter->cursor->parent)) { - iter->cursor = iter->cursor->parent; - } - - if ((iter->flags&RBI_BREAK) == RBI_BREAK) { - libcdsb_rbtree_iter_init(iter, &iter->cursor, iter->flags&~RBI_BREAK); - } else libcdsb_rbtree_iter_init(iter, &iter->cursor, iter->flags); -} - - -rbnode_t* libcdsb_rbtree_iter_next(rbiter_t* iter) { - - rbnode_t* c; - - c = iter->cursor; - - if (rbnode_is_empty(c)) - return rbnode_empty; - - if (!(iter->flags&RBI_FIRST)) { - if (rbnode_is_root(c)) { - if ((iter->flags&RBI_BREAK) == RBI_INORDER) { - iter->flags |= RBI_BREAK; - } else { - libcdsb_rbtree_iter_reset(iter); - if (iter->flags&RBI_POSTORDER) { - iter->flags |= RBI_BREAK; - return c; - } else return rbnode_empty; - } - } - } else if ((iter->flags&RBI_BREAK) == RBI_BREAK) { - iter->flags = (iter->flags&~(RBI_BREAK^RBI_POSTORDER)); - return rbnode_empty; - } else iter->flags &= ~RBI_FIRST; - - switch (iter->flags&RBI_BREAK) { - case RBI_POSTORDER: iter->cursor = postorder_next(c, iter->flags); break; - case RBI_PREORDER: iter->cursor = preorder_next(c, iter->flags); break; - case RBI_INORDER: - default: iter->cursor = inorder_next(c, iter->flags); break; - } - - return c; -}