libcdsb/src/set/base.c

104 lines
2.6 KiB
C
Raw Normal View History

2022-06-06 11:23:33 +03:00
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "../../include/set.h"
#include "../__internal/rbtree.h"
2022-06-08 09:58:49 +03:00
void vset_init(set_t* x, vtype t) {
2022-06-06 11:23:33 +03:00
x->root = rbnode_empty;
x->type = t;
}
2022-06-08 09:58:49 +03:00
void vset_free(set_t* x) {
2022-06-06 11:23:33 +03:00
rbnode_t* t;
rbnode_t* c;
c = x->root;
2022-06-06 11:23:33 +03:00
while (!rbnode_is_empty(x->root)) {
if (!rbnode_is_empty(c->left)) {
c = c->left;
} else if (!rbnode_is_empty(c->right)) {
c = c->right;
} else if (!rbnode_is_root(c)) {
vnode_free(&c->value, x->type);
t = c;
c = c->parent;
if (t == c->left) c->left = rbnode_empty;
else c->right = rbnode_empty;
free(t);
} else {
vnode_free(&c->value, x->type);
x->root = rbnode_empty;
}
}
x->type = 0;
}
2022-06-08 09:58:49 +03:00
size_t vset_size(const set_t* x) {
stack_t z = { .prev = 0, .value = x->root };
size_t n = 0;
rbnode_t* c;
2022-06-06 11:23:33 +03:00
2022-06-08 09:58:49 +03:00
if (!rbnode_is_empty(x->root)) {
while ((c = stack_pop(&z))) {
++n;
if (!rbnode_is_empty(c->left))
stack_push(&z, c->left);
if (!rbnode_is_empty(c->right))
stack_push(&z, c->right);
}
2022-06-06 11:23:33 +03:00
}
return n;
}
2022-06-08 09:58:49 +03:00
int vset_compare(const set_t* s0, const set_t* s1) {
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(&z, s1->root);
stack_push(&z, s0->root);
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(&z);
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(&z); return c; }
} else {
stack_push(&z, c1->right);
stack_push(&z, c0->right);
stack_push(&z, c1->left);
stack_push(&z, c0->left);
}
}
return 0;
2022-06-06 11:23:33 +03:00
}