]> git.mdlowis.com Git - projs/libcds.git/commitdiff
handle more deletion cases & add tests
authora bellenir <a@bellenir.com>
Wed, 6 Aug 2014 21:12:35 +0000 (21:12 +0000)
committera bellenir <a@bellenir.com>
Wed, 6 Aug 2014 21:12:35 +0000 (21:12 +0000)
source/rb/rb.c
tests/test_rb.c

index b05515ebaadbe5b18c84b4f22bcd14625bc2935c..dccd0e2a4b64bed72bb261f0baab799a99a28236 100644 (file)
@@ -175,11 +175,32 @@ static void rb_tree_delete_node(rb_tree_t* tree, rb_node_t* node){
                //has two children. TODO
        }else{
                rb_node_t* parent = node->parent;
-               if(RED == node->color){
+               if(RED == node_color(node)){
                        if(node == parent->left) parent->left = NULL;
                        else parent->right = NULL;
                        node->parent = NULL;
                        mem_release(node);
+               } else if(RED == node_color(node->left) && BLACK == node_color(node->right)){
+                       //single red child, to the left
+                       rb_node_t* child = node->left;
+                       child->parent = parent;
+                       if(parent->left == node) parent->left = child;
+                       else parent->right = child;
+                       //safe to destroy node->right ; it is a NULL leaf
+                       child->color = BLACK;
+                       node->left = NULL;
+                       node->parent = NULL;
+                       mem_release(node);
+               } else if(RED == node_color(node->right) && BLACK == node_color(node->left)){
+                       //single red child, to the right
+                       rb_node_t* child = node->right;
+                       child->parent = parent;
+                       if(parent->left == node) parent->left = child;
+                       else parent->right = child;
+                       child->color = BLACK;
+                       node->right = NULL;
+                       node->parent = NULL;
+                       mem_release(node);
                }
        }
 }
index 49453914ffe6e4330187d2eac12956a919918519..e93fe86cfe2af5f1d2eab448d27b1c2283d64d26 100644 (file)
@@ -310,7 +310,7 @@ TEST_SUITE(RB) {
                mem_release(node4);
                mem_release(tree);
     }
-    TEST(Verify_rb_delete_black_node_with_single_red_child){
+    TEST(Verify_rb_delete_left_black_node_with_single_red_left_child){
                rb_tree_t* tree = rb_tree_new();
                rb_node_t* node1 = rb_tree_insert(tree, 42);
                rb_node_t* node2 = rb_tree_insert(tree, 33);
@@ -337,7 +337,87 @@ TEST_SUITE(RB) {
                mem_release(node2);
                mem_release(tree);
     }
-
+    TEST(Verify_rb_delete_left_black_node_with_single_red_right_child){
+               rb_tree_t* tree = rb_tree_new();
+               rb_node_t* node1 = rb_tree_insert(tree, 42);
+               rb_node_t* node2 = rb_tree_insert(tree, 33);
+               rb_node_t* node3 = rb_tree_insert(tree, 88);
+               rb_node_t* node4 = rb_tree_insert(tree, 38);
+               mem_retain(node2);
+               //delete node 2
+               rb_tree_delete(tree, 33);
+               CHECK(1 == mem_num_references(node2));
+               CHECK(node1 == tree->root);
+               CHECK(node4 == node1->left);
+               CHECK(node3 == node1->right);
+               CHECK(NULL == node4->left);
+               CHECK(NULL == node4->right);
+               CHECK(node1 == node4->parent);
+               CHECK(BLACK == node1->color);
+               CHECK(BLACK == node3->color);
+               CHECK(BLACK == node4->color);
+               //check node2 pointers are nulld
+               CHECK(NULL == node2->parent);
+               CHECK(NULL == node2->left);
+               CHECK(NULL == node2->right);
+               CHECK(rb_tree_is_valid(tree));
+               mem_release(node2);
+               mem_release(tree);
+    }
+    TEST(Verify_rb_delete_right_black_node_with_single_red_right_child){
+               rb_tree_t* tree = rb_tree_new();
+               rb_node_t* node1 = rb_tree_insert(tree, 42);
+               rb_node_t* node2 = rb_tree_insert(tree, 33);
+               rb_node_t* node3 = rb_tree_insert(tree, 88);
+               rb_node_t* node4 = rb_tree_insert(tree, 98);
+               mem_retain(node3);
+               //delete node 3
+               rb_tree_delete(tree, 88);
+               CHECK(1 == mem_num_references(node3));
+               CHECK(node1 == tree->root);
+               CHECK(node2 == node1->left);
+               CHECK(node4 == node1->right);
+               CHECK(NULL == node4->left);
+               CHECK(NULL == node4->right);
+               CHECK(node1 == node4->parent);
+               CHECK(BLACK == node1->color);
+               CHECK(BLACK == node2->color);
+               CHECK(BLACK == node4->color);
+               //check node3 pointers are nulld
+               CHECK(NULL == node3->parent);
+               CHECK(NULL == node3->left);
+               CHECK(NULL == node3->right);
+               CHECK(rb_tree_is_valid(tree));
+               mem_release(node3);
+               mem_release(tree);
+    }
+    TEST(Verify_rb_delete_right_black_node_with_single_red_left_child){
+               rb_tree_t* tree = rb_tree_new();
+               rb_node_t* node1 = rb_tree_insert(tree, 42);
+               rb_node_t* node2 = rb_tree_insert(tree, 33);
+               rb_node_t* node3 = rb_tree_insert(tree, 88);
+               rb_node_t* node4 = rb_tree_insert(tree, 68);
+               mem_retain(node3);
+               //delete node 3
+               rb_tree_delete(tree, 88);
+               CHECK(1 == mem_num_references(node3));
+               CHECK(node1 == tree->root);
+               CHECK(node2 == node1->left);
+               CHECK(node4 == node1->right);
+               CHECK(NULL == node4->left);
+               CHECK(NULL == node4->right);
+               CHECK(node1 == node4->parent);
+               CHECK(BLACK == node1->color);
+               CHECK(BLACK == node2->color);
+               CHECK(BLACK == node4->color);
+               //check node3 pointers are nulld
+               CHECK(NULL == node3->parent);
+               CHECK(NULL == node3->left);
+               CHECK(NULL == node3->right);
+               CHECK(rb_tree_is_valid(tree));
+               mem_release(node3);
+               mem_release(tree);
+    }
        //second class: deleting nodes that have two children
        //third class: special cases
        TEST(Verify_rb_delete_root){}