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-07 21:41:09 +03:00
|
|
|
|
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;
|
|
|
|
|
2022-06-07 21:41:09 +03:00
|
|
|
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) {
|
2022-06-08 00:11:42 +03:00
|
|
|
stack_t z = { .prev = 0, .value = x->root };
|
2022-06-07 21:41:09 +03:00
|
|
|
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) {
|
2022-06-08 00:11:42 +03:00
|
|
|
stack_t z = { .prev = 0, .value = 0 };
|
2022-06-07 21:41:09 +03:00
|
|
|
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;
|
|
|
|
|
2022-06-08 00:11:42 +03:00
|
|
|
stack_push(&z, s1->root);
|
|
|
|
stack_push(&z, s0->root);
|
2022-06-07 21:41:09 +03:00
|
|
|
|
2022-06-08 00:11:42 +03:00
|
|
|
for (rbnode_t *c0, *c1;!is_null(z.value);) {
|
|
|
|
c0 = stack_pop(&z);
|
|
|
|
c1 = stack_pop(&z);
|
2022-06-07 21:41:09 +03:00
|
|
|
|
|
|
|
if (rbnode_is_empty(c0) || rbnode_is_empty(c1)) {
|
|
|
|
if (c0 != c1) {
|
2022-06-08 00:11:42 +03:00
|
|
|
stack_flush(&z);
|
2022-06-07 21:41:09 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-06-08 00:11:42 +03:00
|
|
|
if (c) { stack_flush(&z); return c; }
|
2022-06-07 21:41:09 +03:00
|
|
|
} else {
|
2022-06-08 00:11:42 +03:00
|
|
|
stack_push(&z, c1->right);
|
|
|
|
stack_push(&z, c0->right);
|
|
|
|
stack_push(&z, c1->left);
|
|
|
|
stack_push(&z, c0->left);
|
2022-06-07 21:41:09 +03:00
|
|
|
}
|
|
|
|
}
|
2022-06-08 00:11:42 +03:00
|
|
|
|
|
|
|
return 0;
|
2022-06-06 11:23:33 +03:00
|
|
|
}
|