diff --git a/src/set/base.c b/src/set/base.c index 0b93fbb..141801a 100644 --- a/src/set/base.c +++ b/src/set/base.c @@ -4,36 +4,6 @@ #include "../../include/set.h" #include "../__internal/rbtree.h" -/*#####################################################################################################################*/ - - -static int tree_compare(rbiter_t* s0, rbiter_t* s1, vtype t) { - rbnode_t* p0; - rbnode_t* p1; - int cmp; - - for(;;) { - p0 = rbiter_next(s0); - p1 = rbiter_next(s1); - - if (rbnode_is_empty(p0) || rbnode_is_empty(p1)) { - goto end_; - } else cmp = vnode_compare(&p0->value, t, &p1->value, t); - - if (cmp != 0) break; - } - - for(;;) { - p0 = rbiter_next(s0); - p1 = rbiter_next(s1); - - if (rbnode_is_empty(p0) || rbnode_is_empty(p1)) { - end_: - if (p0 == p1) return cmp; - return (rbnode_is_empty(p0)) ? -1 : 1; - } - } -} /*#####################################################################################################################*/ @@ -43,10 +13,13 @@ void vset_init(vtype_set* x, vtype t) { x->type = t; } + void vset_free(vtype_set* x) { rbnode_t* t; rbnode_t* c; + c = x->root; + while (!rbnode_is_empty(x->root)) { if (!rbnode_is_empty(c->left)) { c = c->left; @@ -71,28 +44,61 @@ void vset_free(vtype_set* x) { x->type = 0; } + size_t vset_size(const vtype_set* x) { - size_t n; - rbiter_t i; + stack_t s = { .prev = 0, .value = x->root }; + size_t n = 0; + rbnode_t* c; - n = 0; - - if (rbiter_init(&i, &x->root, 0)) { - while (!rbnode_is_empty(rbiter_next(&i))) - ++n; + while ((c = stack_pop(&s))) { + ++n; + if (!rbnode_is_empty(c->left)) + stack_push(&s, c->left); + if (!rbnode_is_empty(c->right)) + stack_push(&s, c->right); } return n; } + int vset_compare(const vtype_set* s0, const vtype_set* s1) { - rbiter_t iter[2]; + stack_t s = { .prev = 0, .value = 0 }; + vtype t = s0->type; + int c = 0; - if (s0 == s1) return 0; - if (s0->type == s1->type) { - rbiter_init(iter+0, &s0->root, RBI_INORDER); - rbiter_init(iter+1, &s1->root, RBI_INORDER); + if (s0 == s1 || s0->root == s1->root) return 0; + if (s0->type != s1->type) return s0->type - s1->type; - return tree_compare(iter+0, iter+1, s0->type); - } else return s0->type < s1->type ? -1 : 1; + stack_push(&s, s0->root); + stack_push(&s, s1->root); + + for (rbnode_t *c0, *c1;;) { + c0 = stack_pop(&s); + c1 = stack_pop(&s); + + if (is_null(c0)) return 0; + + if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) { + if (c0 != c1) { + stack_flush(&s); + return rbnode_is_empty(c0) ? -1 : 1; + } + } else if ((c = vnode_compare(c0->value, t, c1->value, t))) { + if (c0->left == c1->right) { + c = vnode_compare(c1->value, t, c0->right->value, t); + if (!c) c = vnode_compare(c1->left->value, t, c0->value, t); + } else if (c0->right == c1->left) { + c = vnode_compare(c0->value, t, c1->right->value, t); + if (!c) c = vnode_compare(c0->left->value, t, c1->value, t); + } + + if (c) { stack_flush(&s); return c; } + } else { + stack_push(&s, c0->left); + stack_push(&s, c1->left); + stack_push(&s, c0->right); + stack_push(&s, c1->right); + } + } }