diff --git a/src/tree/vieter_tree_balancing.c b/src/tree/vieter_tree_balancing.c index 710203b..96b0c10 100644 --- a/src/tree/vieter_tree_balancing.c +++ b/src/tree/vieter_tree_balancing.c @@ -21,8 +21,12 @@ bool vieter_tree_node_validate(vieter_tree_node *node, vieter_tree_node_get(node->children[0], vieter_tree_node_black)) && (node->children[1] == NULL || vieter_tree_node_get(node->children[1], vieter_tree_node_black))); + bool right_child_flag_set = + node->parent == NULL || + (vieter_tree_node_get(node, vieter_tree_node_right) == + (node->parent->children[1] == node)); - return correctly_colored_children && + return correctly_colored_children && right_child_flag_set && vieter_tree_node_validate(node->children[0], passed_black_nodes, expected_black_nodes) && vieter_tree_node_validate(node->children[1], passed_black_nodes, @@ -128,6 +132,14 @@ vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, bool dir) { vieter_tree_node *new_root = old_root->children[1 - dir]; + if (old_root->parent != NULL) { + vieter_tree_node_set_child( + old_root->parent, new_root, + vieter_tree_node_get(old_root, vieter_tree_node_right)); + } else { + new_root->parent = NULL; + } + // Right rotation if (dir) { vieter_tree_node_set_child(old_root, new_root->children[1], false); diff --git a/src/tree/vieter_tree_balancing.h b/src/tree/vieter_tree_balancing.h index befc035..0d1acc5 100644 --- a/src/tree/vieter_tree_balancing.h +++ b/src/tree/vieter_tree_balancing.h @@ -17,4 +17,5 @@ void vieter_tree_node_balance_after_insert(vieter_tree_node *node); */ void vieter_tree_node_remove_balanced(vieter_tree_node *node); +vieter_tree_node *vieter_tree_node_rotate(vieter_tree_node *old_root, bool dir); #endif diff --git a/test/tree/test_balancing.c b/test/tree/test_balancing.c new file mode 100644 index 0000000..5794ab9 --- /dev/null +++ b/test/tree/test_balancing.c @@ -0,0 +1,56 @@ +#include "acutest.h" +#include "vieter_tree_internal.h" +#include "vieter_tree_node.h" +#include "vieter_tree_balancing.h" + +void test_rotate_right() { + vieter_tree_node *a = vieter_tree_node_init(); + vieter_tree_node *b = vieter_tree_node_init(); + vieter_tree_node *p = vieter_tree_node_init(); + + vieter_tree_node_set_child(p, a, false); + vieter_tree_node_set_child(p, b, true); + + vieter_tree_node *c = vieter_tree_node_init(); + vieter_tree_node *q = vieter_tree_node_init(); + + vieter_tree_node_set_child(q, p, false); + vieter_tree_node_set_child(q, c, true); + + vieter_tree_node *new_root = vieter_tree_node_rotate(q, true); + + TEST_CHECK(new_root == p); + TEST_CHECK(new_root->children[0] == a); + TEST_CHECK(new_root->children[1] == q); + TEST_CHECK(new_root->children[1]->children[0] == b); + TEST_CHECK(new_root->children[1]->children[1] == c); +} + +void test_rotate_left() { + vieter_tree_node *b = vieter_tree_node_init(); + vieter_tree_node *c = vieter_tree_node_init(); + vieter_tree_node *q = vieter_tree_node_init(); + + vieter_tree_node_set_child(q, b, false); + vieter_tree_node_set_child(q, c, true); + + vieter_tree_node *a = vieter_tree_node_init(); + vieter_tree_node *p = vieter_tree_node_init(); + + vieter_tree_node_set_child(p, a, false); + vieter_tree_node_set_child(p, q, true); + + vieter_tree_node *new_root = vieter_tree_node_rotate(p, false); + + TEST_CHECK(new_root == q); + TEST_CHECK(new_root->children[0] == p); + TEST_CHECK(new_root->children[1] == c); + TEST_CHECK(new_root->children[0]->children[0] == a); + TEST_CHECK(new_root->children[0]->children[1] == b); +} + +TEST_LIST = { + {"tree tree rotate right", test_rotate_right}, + {"tree tree rotate left", test_rotate_left}, + {NULL, NULL} +}; diff --git a/test/tree/test_tree.c b/test/tree/test_tree.c index 257ec66..6fdd430 100644 --- a/test/tree/test_tree.c +++ b/test/tree/test_tree.c @@ -42,7 +42,7 @@ void test_remove() { void *out; - for (uint64_t i = 0; i < 25; i++) { + for (uint64_t i = 0; i < 100; i++) { TEST_CHECK(vieter_tree_search(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_remove(&out, tree, i) == vieter_tree_ok); TEST_CHECK(vieter_tree_validate(tree));