Update implementation of set (recursion => stack)

This commit is contained in:
Gregory Lirent 2022-06-08 00:11:42 +03:00
parent 0922870d04
commit 05bed02ad9
3 changed files with 98 additions and 62 deletions

View File

@ -5,9 +5,6 @@
#include "../__internal/rbtree.h"
/*#####################################################################################################################*/
void vset_init(vtype_set* x, vtype t) {
x->root = rbnode_empty;
x->type = t;
@ -46,16 +43,16 @@ void vset_free(vtype_set* x) {
size_t vset_size(const vtype_set* x) {
stack_t s = { .prev = 0, .value = x->root };
stack_t z = { .prev = 0, .value = x->root };
size_t n = 0;
rbnode_t* c;
while ((c = stack_pop(&s))) {
while ((c = stack_pop(&z))) {
++n;
if (!rbnode_is_empty(c->left))
stack_push(&s, c->left);
stack_push(&z, c->left);
if (!rbnode_is_empty(c->right))
stack_push(&s, c->right);
stack_push(&z, c->right);
}
return n;
@ -63,25 +60,23 @@ size_t vset_size(const vtype_set* x) {
int vset_compare(const vtype_set* s0, const vtype_set* s1) {
stack_t s = { .prev = 0, .value = 0 };
stack_t z = { .prev = 0, .value = 0 };
vtype t = s0->type;
int c = 0;
if (s0 == s1 || s0->root == s1->root) return 0;
if (s0->type != s1->type) return s0->type - s1->type;
stack_push(&s, s0->root);
stack_push(&s, s1->root);
stack_push(&z, s1->root);
stack_push(&z, s0->root);
for (rbnode_t *c0, *c1;;) {
c0 = stack_pop(&s);
c1 = stack_pop(&s);
if (is_null(c0)) return 0;
for (rbnode_t *c0, *c1;!is_null(z.value);) {
c0 = stack_pop(&z);
c1 = stack_pop(&z);
if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) {
if (c0 != c1) {
stack_flush(&s);
stack_flush(&z);
return rbnode_is_empty(c0) ? -1 : 1;
}
} else if ((c = vnode_compare(c0->value, t, c1->value, t))) {
@ -93,12 +88,14 @@ int vset_compare(const vtype_set* s0, const vtype_set* s1) {
if (!c) c = vnode_compare(c0->left->value, t, c1->value, t);
}
if (c) { stack_flush(&s); return c; }
if (c) { stack_flush(&z); return c; }
} else {
stack_push(&s, c0->left);
stack_push(&s, c1->left);
stack_push(&s, c0->right);
stack_push(&s, c1->right);
stack_push(&z, c1->right);
stack_push(&z, c0->right);
stack_push(&z, c1->left);
stack_push(&z, c0->left);
}
}
return 0;
}

View File

@ -4,56 +4,102 @@
#include "../../include/set.h"
#include "../__internal/rbtree.h"
/*#####################################################################################################################*/
static void copy_child(rbnode_t* x, vtype t, const rbnode_t* l, const rbnode_t* r) {
if (!rbnode_is_empty(l)) {
x->left = rbnode_create(vnode_duplicate(&l->value, t), x, l->colored);
copy_child(x->left, t, l->left, l->right);
} else x->left = rbnode_empty;
if (!rbnode_is_empty(r)) {
x->left = rbnode_create(vnode_duplicate(&r->value, t), x, r->colored);
copy_child(x->right, t, r->right, r->right);
} else x->right = rbnode_empty;
}
/*#####################################################################################################################*/
vtype_set vset_copy(const vtype_set* s) {
set_t x = { .type = s->type };
set_t x = { .type = s->type };
stack_t z = { .prev = 0, .value = s->root };
vtype t = s->type;
if (!rbnode_is_empty(s->root)) {
x.root = rbnode_create(vnode_duplicate(&s->root->value, s->type), rbnode_empty, 0);
x.root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0);
stack_push(&z, x.root);
do {
rbnode_t *p0, *p1;
p0 = stack_pop(&z);
p1 = stack_pop(&z);
if (!rbnode_is_empty(p1->left)) {
p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored);
stack_push(&z, p1->left);
stack_push(&z, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push(&z, p1->right);
stack_push(&z, p0->right);
}
} while (!is_null(z.value));
copy_child(x.root, s->type, s->root->left, s->root->right);
} else x.root = rbnode_empty;
return x;
}
vtype_set* vset_duplicate(const vtype_set* s) {
set_t* x = malloc(sizeof(*x));
x->type = s->type;
vtype_set* vset_duplicate(const vtype_set* s) {
set_t* x = malloc(sizeof(*x));
stack_t z = { .prev = 0, .value = s->root };
vtype t = x->type = s->type;
if (!rbnode_is_empty(s->root)) {
x->root = rbnode_create(vnode_duplicate(&s->root->value, s->type), rbnode_empty, 0);
x->root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0);
stack_push(&z, x->root);
do {
rbnode_t *p0 = stack_pop(&z);
rbnode_t *p1 = stack_pop(&z);
if (!rbnode_is_empty(p1->left)) {
p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored);
stack_push(&z, p1->left);
stack_push(&z, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push(&z, p1->right);
stack_push(&z, p0->right);
}
} while (!is_null(z.value));
copy_child(x->root, s->type, s->root->left, s->root->right);
} else x->root = rbnode_empty;
return x;
}
void vset_copy_init(vtype_set* x, const vtype_set* s) {
x->type = s->type;
stack_t z = { .prev = 0, .value = s->root };
vtype t = x->type = s->type;
if (!rbnode_is_empty(s->root)) {
x->root = rbnode_create(vnode_duplicate(&s->root->value, s->type), rbnode_empty, 0);
x->root = rbnode_create(vnode_duplicate(&s->root->value, t), rbnode_empty, 0);
stack_push(&z, x->root);
do {
rbnode_t *p0 = stack_pop(&z);
rbnode_t *p1 = stack_pop(&z);
if (!rbnode_is_empty(p1->left)) {
p0->left = rbnode_create(vnode_duplicate(&p1->left->value, t), p0, p1->left->colored);
stack_push(&z, p1->left);
stack_push(&z, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push(&z, p1->right);
stack_push(&z, p0->right);
}
} while (!is_null(z.value));
copy_child(x->root, s->type, s->root->left, s->root->right);
} else x->root = rbnode_empty;
}

View File

@ -4,9 +4,6 @@
#include "../../include/extra/set.h"
#include "../__internal/rbtree.h"
/*#####################################################################################################################*/
_Bool libcdsb_vset_find(val_t* x, set_t* s, const void* v, vtype t, _Bool cut) {
rbnode_t* c;
int cmp;
@ -73,25 +70,21 @@ _Bool libcdsb_vset_insert(set_t* x, const void* v, vtype t) {
}
/*#####################################################################################################################*/
int libcdsb_vset_foreach(const set_t* x, void* data, int (*callback)(const void* value, vtype type, void* data)) {
stack_t s = { .prev = 0, .value = x->root };
stack_t z = { .prev = 0, .value = x->root };
int r = 0;
rbnode_t* c;
if (rbnode_is_empty(x->root)) return 0;
while ((c = stack_pop(&s))) {
while ((c = stack_pop(&z))) {
if ((r = callback(vnode_peek(&c->value, x->type), x->type, data))) {
stack_flush(&s);
stack_flush(&z);
break;
}
if (!rbnode_is_empty(c->left))
stack_push(&s, c->left);
if (!rbnode_is_empty(c->right))
stack_push(&s, c->right);
if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
if (!rbnode_is_empty(c->left)) stack_push(&z, c->left);
}
return r;