From: a bellenir Date: Tue, 5 Aug 2014 22:31:11 +0000 (+0000) Subject: WIP; split insert & repaint functions X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=84302bf6723791b4d6e44f045b3099a0aab185f6;p=projs%2Flibcds.git WIP; split insert & repaint functions --- diff --git a/source/rb/rb.c b/source/rb/rb.c index 9fa7ed3..e667cc0 100644 --- a/source/rb/rb.c +++ b/source/rb/rb.c @@ -32,12 +32,55 @@ rb_tree_t* rb_tree_new(){ return tree; } +//leaves are NULL and black implicitly +static rb_color_t node_color(rb_node_t* node){ + return (node ? node->color : BLACK); +} + +//NODE:the node to be inserted +static void rb_tree_recolor( + rb_node_t* node, rb_node_t* parent, + rb_node_t* grandparent, rb_node_t* uncle +){ + if(NULL == parent){ + node->color = BLACK; + }else if(BLACK == node_color(parent)){ + /* dont need to do anything */ + }else if(node_color(parent) == BLACK && node_color(uncle) == BLACK){ + grandparent->color = RED; + parent->color = BLACK; + uncle->color = BLACK; + }else{ + //TODO + } +} +static void rb_tree_insert_node(rb_tree_t* tree, + rb_node_t* node, rb_node_t* parent, + rb_node_t* grandparent, rb_node_t* uncle +){ + if(NULL == parent){ /* inserting root of the tree */ + tree->root = node; + rb_tree_recolor(node, parent, grandparent, uncle); + }else if(node->contents < parent->contents){ + if(parent->left){ + rb_tree_insert_node(tree, node, parent->left, parent, parent->right); + }else{ + parent->left = node; + rb_tree_recolor(node, parent, grandparent, uncle); + } + }else{ + if(parent->right){ + rb_tree_insert_node(tree, node, parent->right, parent, parent->left); + }else{ + parent->right = node; + rb_tree_recolor(node, parent, grandparent, uncle); + } + } +} + rb_node_t* rb_tree_insert(rb_tree_t* tree, int value){ rb_node_t* new_node = rb_node_new(value); - if(NULL == tree->root){ - new_node->color = BLACK; - tree->root = new_node; - } + rb_tree_insert_node(tree, new_node, tree->root, NULL, NULL); return new_node; } @@ -62,8 +105,8 @@ bool rb_node_is_valid(rb_node_t* node, int min_val, int max_val){ if(node){ ret &= (node->color == RED || node->color == BLACK); if(node->color == RED){ - ret &= (!node->left || node->left->color == BLACK); - ret &= (!node->right || node->right->color == BLACK); + ret &= ((node_color(node->left) == BLACK) && + (node_color(node->right) == BLACK)); } ret &= ( -1 == min_val || node->contents >= min_val); ret &= ( -1 == max_val || node->contents <= max_val); diff --git a/tests/test_rb.c b/tests/test_rb.c index 3b75bce..e920c35 100644 --- a/tests/test_rb.c +++ b/tests/test_rb.c @@ -45,5 +45,51 @@ TEST_SUITE(RB) { CHECK(rb_tree_is_valid(tree)); mem_release(tree); } + TEST(Verify_rb_insert_node_to_root_left_works){ + rb_tree_t* tree = rb_tree_new(); + rb_node_t* root = rb_tree_insert(tree, 42); + rb_node_t* node1 = rb_tree_insert(tree, 31); + CHECK(NULL != root); + CHECK(NULL != node1); + CHECK(tree->root == root); + CHECK(31 == node1->contents); + CHECK(node1 == root->left); + CHECK(NULL == root->right); + CHECK(RED == node1->color); + CHECK(rb_tree_is_valid(tree)); + mem_release(tree); + } + TEST(Verify_rb_insert_node_to_root_right_works){ + rb_tree_t* tree = rb_tree_new(); + rb_node_t* root = rb_tree_insert(tree, 42); + rb_node_t* node2 = rb_tree_insert(tree, 64); + CHECK(NULL != root); + CHECK(NULL != node2); + CHECK(tree->root == root); + CHECK(64 == node2->contents); + CHECK(node2 == root->right); + CHECK(NULL == root->left); + CHECK(RED == node2->color); + CHECK(rb_tree_is_valid(tree)); + mem_release(tree); + } + TEST(Verify_rb_insert_first_level_works){ + rb_tree_t* tree = rb_tree_new(); + rb_node_t* root = rb_tree_insert(tree, 42); + rb_node_t* node1 = rb_tree_insert(tree, 31); + rb_node_t* node2 = rb_tree_insert(tree, 64); + CHECK(NULL != root); + CHECK(NULL != node1); + CHECK(NULL != node2); + CHECK(tree->root == root); + CHECK(31 == node1->contents); + CHECK(64 == node2->contents); + CHECK(node1 == root->left); + CHECK(node2 == root->right); + CHECK(RED == node1->color); + CHECK(RED == node2->color); + CHECK(rb_tree_is_valid(tree)); + mem_release(tree); + } }