Change iteration implementation to the stack based
This commit is contained in:
parent
8a813e877a
commit
b6a97576e4
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user