Clean the rbtree implementation

This commit is contained in:
Gregory Lirent 2022-06-07 21:34:30 +03:00
parent 9a34d1d71f
commit e94cdc9783
2 changed files with 7 additions and 210 deletions

View File

@ -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)

View File

@ -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;
}