Tests for insertion passed + written _find(), _at() methods
This commit is contained in:
parent
bcc20b2f6e
commit
36ef29cff1
@ -6,8 +6,8 @@
|
||||
/* When key is given by value into some method of Buff_RBTreeSet */
|
||||
NODISCARD VecU8 codegen_rb_tree_set_key_value_NOT_EQUAL_element(set_instantiation_op op){
|
||||
if (op.t_integer)
|
||||
return VecU8_fmt("self->el.buf[cur - 1] != key");
|
||||
return VecU8_fmt("!%s_equal_%s(&self->el.buf[cur - 1], &key)", op.T, op.T);
|
||||
return VecU8_fmt("key != self->el.buf[cur - 1]");
|
||||
return VecU8_fmt("!%s_equal_%s(&key, &self->el.buf[cur - 1])", op.T, op.T);
|
||||
}
|
||||
|
||||
/* When key is given by value into some method of Buff_RBTreeSet */
|
||||
@ -17,17 +17,25 @@ NODISCARD VecU8 codegen_rb_tree_set_key_value_LESS_element(set_instantiation_op
|
||||
return VecU8_fmt("%s_less_%s(&key, &self->el.buf[cur - 1])", op.T, op.T);
|
||||
}
|
||||
|
||||
/* When key is given by ref into some method of Buff_RBTreeSet
|
||||
* Ofk when op.T is integer, argument is still taken by a value */
|
||||
NODISCARD VecU8 codegen_rb_tree_set_key_ref_NOT_EQUAL_element(set_instantiation_op op){
|
||||
if (op.t_integer)
|
||||
return VecU8_fmt("key != self->el.buf[cur - 1]");
|
||||
return VecU8_fmt("!%s_equal_%s(key, &self->el.buf[cur - 1])", op.T, op.T);
|
||||
}
|
||||
|
||||
/* When key is given by a pointer into some method of Buff_RBTreeSet */
|
||||
NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op op){
|
||||
if (op.t_integer)
|
||||
return VecU8_fmt("self->el.buf[cur - 1] == key");
|
||||
return VecU8_fmt("%s_equal_%s(&self->el.buf[cur - 1], key)", op.T, op.T);
|
||||
return VecU8_fmt("key == self->el.buf[cur - 1]");
|
||||
return VecU8_fmt("%s_equal_%s(ref, &self->el.buf[cur - 1])", op.T, op.T);
|
||||
}
|
||||
|
||||
/* When key is given by a pointer into some method of Buff_RBTreeSet */
|
||||
NODISCARD VecU8 codegen_rb_tree_set_key_ref_LESS_element(set_instantiation_op op){
|
||||
if (op.t_integer)
|
||||
return VecU8_fmt("self->el.buf[cur - 1] < key");
|
||||
return VecU8_fmt("key < self->el.buf[cur - 1]");
|
||||
return VecU8_fmt("%s_less_%s(key, &self->el.buf[cur - 1])", op.T, op.T);
|
||||
}
|
||||
|
||||
@ -162,6 +170,11 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op
|
||||
SPACE "Vec%s el;\n"
|
||||
"} %s;\n\n", op.T, set));
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"NODISCARD %s %s_new() {\n"
|
||||
SPACE "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new()};\n"
|
||||
"}\n\n", set, set, set, op.T));
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"void %s_drop(%s self) {\n"
|
||||
SPACE "VecRBTreeNode_drop(self.tree);\n"
|
||||
@ -179,19 +192,21 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op
|
||||
"return false;\n",
|
||||
op.T));
|
||||
|
||||
/* Method _erase_substitute() is a mole bald version of _insert() method. It will substitute
|
||||
* previous element with equal key it it was found. It still returns true if no conflict has happened, though */
|
||||
codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("erase_substitute"), vcstr("bool"),
|
||||
vcstr("return true;\n"),
|
||||
op.t_integer ?
|
||||
vcstr("return false;\n") :
|
||||
VecU8_fmt(
|
||||
"%s_drop(self->el.buf[cur - 1]);\n"
|
||||
"self->el.buf[cur - 1] = key;\n"
|
||||
"return false;\n"
|
||||
));
|
||||
|
||||
if (!op.t_integer) {
|
||||
/* Method _erase_substitute() is a more bald version of _insert() method. It will substitute
|
||||
* previous element with equal key it it was found. It still returns true if no conflict has happened, though */
|
||||
codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("erase_substitute"), vcstr("bool"),
|
||||
vcstr("return true;\n"),
|
||||
op.t_integer ?
|
||||
vcstr("return false;\n") :
|
||||
VecU8_fmt(
|
||||
"%s_drop(self->el.buf[cur - 1]);\n"
|
||||
"self->el.buf[cur - 1] = key;\n"
|
||||
"return false;\n"
|
||||
));
|
||||
|
||||
/* Method _pop_substitute() is just like _erase_substitute(), but it returns a previous key
|
||||
* that was overthrown after collision. Wrapped in option, ofcourse */
|
||||
codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("pop_substitute"),
|
||||
codegen_rb_tree_set_option_returned_value_t(op),
|
||||
VecU8_fmt("return %v;\n", codegen_rb_tree_set_none_t(op)),
|
||||
@ -224,7 +239,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op
|
||||
SPACE SPACE "self->root = x;\n"
|
||||
SPACE "else if (self->tree.buf[py].left == y)\n"
|
||||
SPACE SPACE "self->tree.buf[py].left = x;\n"
|
||||
SPACE "else"
|
||||
SPACE "else\n"
|
||||
SPACE SPACE "self->tree.buf[py].right = x;\n"
|
||||
SPACE "RBTreeColor y_org_clr = self->tree.buf[y].color;\n"
|
||||
SPACE "if (z != y)\n"
|
||||
@ -234,7 +249,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op
|
||||
SPACE "self->tree.len--;\n"
|
||||
SPACE "self->el.buf[z-1] = self->el.buf[L-1];\n"
|
||||
SPACE "self->el.len--;\n"
|
||||
SPACE "if (y_org_clr)"
|
||||
SPACE "if (y_org_clr)\n"
|
||||
SPACE SPACE "RBTree_fix_after_delete(self->tree.buf, &self->root, x);\n"
|
||||
SPACE "return true;\n"
|
||||
"}\n\n",
|
||||
@ -243,11 +258,50 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op
|
||||
codegen_rb_tree_set_key_ref_LESS_element(op)
|
||||
));
|
||||
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"U64 %s_find(const %s* self, %v key) {\n" /* set, set taking_ref_t_argument */
|
||||
SPACE "U64 cur = self->root;\n"
|
||||
SPACE "while (cur != 0 && %v) {\n" /* key reference not equal cur element */
|
||||
SPACE SPACE "if (%v) {\n" /* key reference less than cue element */
|
||||
SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n"
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return cur;\n"
|
||||
"}\n\n",
|
||||
set, set, codegen_rb_tree_set_taking_ref_t_argument(op),
|
||||
codegen_rb_tree_set_key_ref_NOT_EQUAL_element(op),
|
||||
codegen_rb_tree_set_key_ref_LESS_element(op)
|
||||
));
|
||||
|
||||
if (!op.t_integer) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"%v %s_at(const %s* self, %v key) {\n" /* option_returned_ref_t, set, set, taking_ref_t_argument */
|
||||
SPACE "U64 cur = self->root;\n"
|
||||
SPACE "while (cur != 0) {\n"
|
||||
SPACE SPACE "if (%v) {\n" /* key_ref_EQUAL_element */
|
||||
SPACE SPACE SPACE "return %v;\n" /* some_ref_t */
|
||||
SPACE SPACE "} else if (%v) {\n" /* key_ref_LESS_element */
|
||||
SPACE SPACE SPACE "cur = self->tree.buf[cur].left;\n"
|
||||
SPACE SPACE "} else {\n"
|
||||
SPACE SPACE SPACE "cur = self->tree.buf[cur].right;\n"
|
||||
SPACE SPACE "}\n"
|
||||
SPACE "}\n"
|
||||
SPACE "return %v;\n" /* none_ref_t */
|
||||
"}\n\n",
|
||||
codegen_rb_tree_set_option_returned_ref_t(op), set, set, codegen_rb_tree_set_taking_ref_t_argument(op),
|
||||
codegen_rb_tree_set_key_ref_EQUAL_element(op),
|
||||
codegen_rb_tree_set_some_ref_t(op, cstr("cur")),
|
||||
codegen_rb_tree_set_key_ref_LESS_element(op),
|
||||
codegen_rb_tree_set_none_ref_t(op)
|
||||
));
|
||||
}
|
||||
|
||||
// todo: continue from here. Implement method _pop_and_substitute()
|
||||
|
||||
// todo: implement contains method
|
||||
// todo: All the other methods are secondary in importance
|
||||
|
||||
// todo: implment _find and _at methods. All the other methods are secondary in importance
|
||||
VecU8_drop(g_set);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ void RBTree_left_rotate(RBTreeNode* tree, U64* root, U64 x){
|
||||
tree[tree[x].right].parent = x;
|
||||
|
||||
tree[y].parent = tree[x].parent;
|
||||
if (tree[y].parent != 0) {
|
||||
if (tree[y].parent == 0) {
|
||||
*root = y;
|
||||
} else if (x == tree[tree[x].parent].left) {
|
||||
tree[tree[x].parent].left = y;
|
||||
@ -47,7 +47,7 @@ void RBTree_right_rotate(RBTreeNode* tree, U64* root, U64 x){
|
||||
tree[tree[x].left].parent = x;
|
||||
|
||||
tree[y].parent = tree[x].parent;
|
||||
if (tree[y].parent != 0) {
|
||||
if (tree[y].parent == 0) {
|
||||
*root = y;
|
||||
} else if (x == tree[tree[x].parent].right) {
|
||||
tree[tree[x].parent].right = y;
|
||||
@ -66,7 +66,7 @@ void RBTree_fix_after_insert(RBTreeNode* tree, U64* root, U64 me){
|
||||
if (mom == 0)
|
||||
break;
|
||||
if (tree[mom].color == RBTree_black)
|
||||
break;
|
||||
return;
|
||||
U64 grandma = tree[mom].parent;
|
||||
U64 aunt = tree[grandma].left == mom ? tree[grandma].right : tree[grandma].left;
|
||||
assert(aunt != mom);
|
||||
|
||||
@ -1,5 +1,177 @@
|
||||
#include "../../../../gen/l1_5/BuffRBTree_SetS64.h"
|
||||
|
||||
void assert_structure_h_dfs(const VecRBTreeNode* tree, U64 x, VecU8* f){
|
||||
if (x == 0)
|
||||
return;
|
||||
if (*VecU8_at(f, x - 1) != 0)
|
||||
assert(false);
|
||||
*VecU8_mat(f, x - 1) = 1;
|
||||
assert_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->left, f);
|
||||
assert_structure_h_dfs(tree, VecRBTreeNode_at(tree, x)->right, f);
|
||||
}
|
||||
|
||||
U32 assert_structure_h_dfs_2(RBTreeNode* tree, U64 x){
|
||||
if (x == 0) {
|
||||
return 0;
|
||||
}
|
||||
U32 a = assert_structure_h_dfs_2(tree, tree[x].left);
|
||||
U32 b = assert_structure_h_dfs_2(tree, tree[x].right);
|
||||
assert(a == b);
|
||||
return a + (tree[x].color == RBTree_black ? 1 : 0);
|
||||
}
|
||||
|
||||
void assert_structure(const BuffRBTree_SetS64* self){
|
||||
assert(self->tree.len == self->el.len + 1);
|
||||
assert(self->root < self->tree.len);
|
||||
if (self->tree.len > 1) {
|
||||
assert(self->root != 0);
|
||||
}
|
||||
VecU8 f = VecU8_new_zeroinit(self->tree.len - 1);
|
||||
assert_structure_h_dfs(&self->tree, self->root, &f);
|
||||
for (size_t i = 0; i < self->tree.len - 1; i++) {
|
||||
assert(*VecU8_at(&f, i));
|
||||
}
|
||||
VecU8_drop(f); /* f invalidated */
|
||||
for (size_t v = 1; v < self->tree.len; v++) {
|
||||
if (v == self->root) {
|
||||
assert(self->tree.buf[v].parent == 0);
|
||||
} else {
|
||||
assert(self->tree.buf[v].parent != 0);
|
||||
}
|
||||
assert(self->tree.buf[v].parent < self->tree.len);
|
||||
assert(self->tree.buf[v].left < self->tree.len);
|
||||
assert(self->tree.buf[v].right < self->tree.len);
|
||||
if (self->tree.buf[v].left != 0) {
|
||||
assert(self->tree.buf[self->tree.buf[v].left].parent == v);
|
||||
assert(self->el.buf[self->tree.buf[v].left - 1] < self->el.buf[v - 1]);
|
||||
}
|
||||
if (self->tree.buf[v].right != 0) {
|
||||
assert(self->tree.buf[self->tree.buf[v].right].parent == v);
|
||||
assert(self->el.buf[v - 1] < self->el.buf[self->tree.buf[v].right - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Checking coloring */
|
||||
assert(self->tree.buf[0].color == RBTree_black);
|
||||
if (self->root != 0)
|
||||
assert(self->tree.buf[self->root].color == RBTree_black);
|
||||
for (size_t v = 1; v < self->tree.len; v++) {
|
||||
if (self->tree.buf[v].color == RBTree_red) {
|
||||
assert(self->tree.buf[self->tree.buf[v].left].color == RBTree_black);
|
||||
assert(self->tree.buf[self->tree.buf[v].right].color == RBTree_black);
|
||||
}
|
||||
}
|
||||
assert_structure_h_dfs_2(self->tree.buf, self->root);
|
||||
}
|
||||
|
||||
void insert_only(){
|
||||
{
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
assert_structure(&set);
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
bool ret = BuffRBTree_SetS64_insert(&set, 42);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
assert(set.el.len == 1);
|
||||
assert(set.root == 1);
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
bool ret;
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
ret = BuffRBTree_SetS64_insert(&set, 42);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
ret = BuffRBTree_SetS64_insert(&set, 69);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
assert(set.el.len == 2);
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
bool ret;
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
ret = BuffRBTree_SetS64_insert(&set, 70);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
ret = BuffRBTree_SetS64_insert(&set, 50);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
assert(set.el.len == 2);
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
bool ret;
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
ret = BuffRBTree_SetS64_insert(&set, 1);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
ret = BuffRBTree_SetS64_insert(&set, 2);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
ret = BuffRBTree_SetS64_insert(&set, 3);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
for (S64 i = 10; i < 100; i++) {
|
||||
bool ret = BuffRBTree_SetS64_insert(&set, i);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
}
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
for (S64 i = 99; i >= 10; i--) {
|
||||
bool ret = BuffRBTree_SetS64_insert(&set, i);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
}
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
for (S64 i = 10; i < 100; i++) {
|
||||
bool ret = BuffRBTree_SetS64_insert(&set, i);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
bool ret2 = BuffRBTree_SetS64_insert(&set, 1000 - i);
|
||||
assert(ret2);
|
||||
assert_structure(&set);
|
||||
}
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
{
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
// BuffRBTree_SetS64_erase_substitute()
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
}
|
||||
|
||||
void insert_and_then_find(){
|
||||
BuffRBTree_SetS64 set = BuffRBTree_SetS64_new();
|
||||
for (S64 p = 0; p < 100; p++) {
|
||||
bool ret = BuffRBTree_SetS64_insert(&set, 2 * p);
|
||||
assert(ret);
|
||||
assert_structure(&set);
|
||||
for (S64 i = 0; i <= p; i++) {
|
||||
U64 ret1 = BuffRBTree_SetS64_find(&set, 2 * i);
|
||||
assert(ret1);
|
||||
U64 ret2 = BuffRBTree_SetS64_find(&set, 2 * i + 1);
|
||||
assert(ret2 == 0);
|
||||
}
|
||||
}
|
||||
BuffRBTree_SetS64_drop(set);
|
||||
}
|
||||
|
||||
int main() {
|
||||
insert_only();
|
||||
insert_and_then_find();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user