Rollback excess abstractions for rbtree's types

This commit is contained in:
2022-08-18 00:15:54 +03:00
parent 3cbf7a6fdf
commit 72770c3561
8 changed files with 468 additions and 314 deletions
+127 -33
View File
@@ -6,10 +6,58 @@
/*#####################################################################################################################*/
hash_t vset_hash(const set_t* s) {
return rbtree_hash(s->root, nullptr, (void*)&s->type) + VTYPE_SET;
static inline int rbnode_compare(const rbnode_t* s0, const rbnode_t* s1, vtype t) {
return vnode_compare(s0->value, t, s1->value, t);
}
static inline hash_t rbnode_hash(const rbnode_t* s, vtype t) {
return vnode_hash(&s->value, t);
}
/*#####################################################################################################################*/
hash_t vset_hash(const set_t* s) {
rbnode_t *c0, *c1;
hash_t hash, v;
stack_t z;
if (rbnode_is_empty(s->root)) return 0;
z.prev = 0;
hash = 1;
c1 = s->root;
if (!rbnode_is_empty(z.value = c1->left)) {
do {
c0 = stack_pop(&z);
++hash;
if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right);
if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left);
} while (!is_null(z.value));
}
v = rbnode_hash(c1, s->type);
c1 = s->root;
if (!rbnode_is_empty(z.value = c1->right)) {
do {
c0 = stack_pop(&z);
++hash;
if (!rbnode_is_empty(c0->right)) stack_push(&z, c1 = c0->right);
if (!rbnode_is_empty(c0->left)) stack_push(&z, c1 = c0->left);
} while (!is_null(z.value));
}
v += rbnode_hash(c1, s->type);
return (hash ^ v) + VTYPE_SET;
}
/*#####################################################################################################################*/
void vset_init(set_t* x, vtype t) {
x->root = rbnode_empty;
x->type = t;
@@ -17,48 +65,94 @@ void vset_init(set_t* x, vtype t) {
void vset_free(set_t* x) {
rbtree_free(x->root, nullptr, &x->type);
rbnode_t *t, *c;
c = x->root;
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->root = rbnode_empty;
x->type = 0;
}
/*#####################################################################################################################*/
size_t vset_size(const set_t* x) {
return rbtree_size(x->root);
stack_t z = { .prev = 0, .value = x->root };
size_t n = 0;
rbnode_t* c;
if (!rbnode_is_empty(x->root)) {
while ((c = stack_pop(&z))) {
++n;
if (!rbnode_is_empty(c->right)) stack_push(&z, c->right);
if (!rbnode_is_empty(c->left)) stack_push(&z, c->left);
}
}
return n;
}
/*#####################################################################################################################*/
int vset_compare(const set_t* s0, const set_t* s1) {
if (s0 == s1) return 0;
if (s0->type != s1->type) return s0->type - s1->type;
rbnode_t *c0, *c1;
stack_t z;
int c = 0;
return rbtree_compare(s0->root, s1->root, nullptr, (void*)&s0->type);
}
/*#####################################################################################################################*/
set_t vset_copy(const set_t* s) {
set_t x;
x.type = s->type;
x.root = rbtree_duplicate(s->root, nullptr, &x.type);
return x;
}
set_t* vset_duplicate(const set_t* s) {
set_t *x = malloc(sizeof(*x));
x->type = s->type;
x->root = rbtree_duplicate(s->root, nullptr, &x->type);
return x;
}
void vset_copy_init(set_t* x, const set_t* s) {
x->type = s->type;
x->root = rbtree_duplicate(s->root, nullptr, &x->type);
if (s0 == s1 || s0->root == s1->root)
return 0;
if (s0->type != s1->type)
return s0->type - s1->type;
z.prev = 0;
z.value = 0;
stack_push_many(&z, 2, (void*)s1, (void*)s0);
do {
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 = rbnode_compare(c0, c1, s0->type))) {
if (c0->left == c1->right) { // == rbnode_empty
c = rbnode_compare(c0->right, c1, s0->type);
if (!c) c = rbnode_compare(c0, c1->left, s0->type);
} else if (c0->right == c1->left) { // == rbnode_empty
c = rbnode_compare(c0, c1->right, s0->type);
if (!c) c = rbnode_compare(c0->left, c1, s0->type);
}
if (c) {
stack_flush(&z);
return c;
}
} else stack_push_many(&z, 4, c1->right, c0->right, c1->left, c0->left);
} while (!is_null(z.value));
return 0;
}
+97
View File
@@ -0,0 +1,97 @@
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "../../include/set.h"
#include "../__internal/rbtree.h"
set_t vset_copy(const set_t* s) {
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, 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_many(&z, 2, p1->left, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x.root = rbnode_empty;
return x;
}
set_t* vset_duplicate(const set_t* 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, 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_many(&z, 2, p1->left, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x->root = rbnode_empty;
return x;
}
void vset_copy_init(set_t* x, const set_t* s) {
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, 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_many(&z, 2, p1->left, p0->left);
}
if (!rbnode_is_empty(p1->right)) {
p0->right = rbnode_create(vnode_duplicate(&p1->right->value, t), p0, p1->right->colored);
stack_push_many(&z, 2, p1->right, p0->right);
}
} while (!is_null(z.value));
} else x->root = rbnode_empty;
}