Change iteration implementation to the stack based

This commit is contained in:
Gregory Lirent 2022-06-07 21:41:09 +03:00
parent 8a813e877a
commit b6a97576e4

View File

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