From: a bellenir Date: Tue, 5 Aug 2014 20:52:01 +0000 (+0000) Subject: red/black check functions X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=413e8d65994620bef43632b1f91baa86f4727673;p=projs%2Flibcds.git red/black check functions --- diff --git a/source/rb/rb.c b/source/rb/rb.c index 07de5f3..9fa7ed3 100644 --- a/source/rb/rb.c +++ b/source/rb/rb.c @@ -1,4 +1,5 @@ #include +#include #include "mem.h" #include "rb.h" @@ -16,7 +17,6 @@ static void rb_node_free(void* v_node){ } } - rb_node_t* rb_node_new(int contents){ rb_node_t* node = mem_allocate(sizeof(rb_node_t), &rb_node_free); node->left = NULL; @@ -32,3 +32,55 @@ rb_tree_t* rb_tree_new(){ return tree; } +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; + } + return new_node; +} + + +/* THE FOLLOWING FUNCTIONS (TO EOF) ARE USED FOR TESTING PURPOSES ONLY */ + +//if path to the left != path to the right, return -1 (invalid) +int count_black_nodes_to_leaf(rb_node_t* node){ + int ret = 0; + if(node){ + int leftcount = count_black_nodes_to_leaf(node->left); + int rightcount = count_black_nodes_to_leaf(node->right); + if(leftcount != rightcount) ret = -1; + else if(node->color == BLACK) ret = leftcount+1; + else ret = leftcount; + } + return ret; +} + +bool rb_node_is_valid(rb_node_t* node, int min_val, int max_val){ + bool ret = true; + 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 &= ( -1 == min_val || node->contents >= min_val); + ret &= ( -1 == max_val || node->contents <= max_val); + ret &= rb_node_is_valid(node->left, min_val, node->contents); + ret &= rb_node_is_valid(node->right, node->contents, max_val); + } + return ret; +} + +//check the contents of the given tree/node as valid +bool rb_tree_is_valid(rb_tree_t* tree){ + bool ret = true; + if(tree){ + ret = rb_node_is_valid(tree->root, -1, -1); + if(tree->root) ret &= (tree->root->color == BLACK); + ret &= (count_black_nodes_to_leaf(tree->root) != -1); + } + return ret; +} + diff --git a/source/rb/rb.h b/source/rb/rb.h index 06dd293..73421d9 100644 --- a/source/rb/rb.h +++ b/source/rb/rb.h @@ -5,6 +5,8 @@ extern "C" { #endif +#include + typedef enum { RED = 0, BLACK @@ -24,6 +26,12 @@ typedef struct { rb_node_t* rb_node_new(int contents); rb_tree_t* rb_tree_new(); +//returns a pointer to the new node +rb_node_t* rb_tree_insert(rb_tree_t* tree, int value); + +//TEST FUNCTIONS: +bool rb_tree_is_valid(rb_tree_t* tree); +bool rb_node_is_valid(rb_node_t* node, int min_val, int max_val); #ifdef __cplusplus } diff --git a/tests/test_rb.c b/tests/test_rb.c index e2440c6..3b75bce 100644 --- a/tests/test_rb.c +++ b/tests/test_rb.c @@ -10,7 +10,7 @@ static void test_setup(void) { } //----------------------------------------------------------------------------- TEST_SUITE(RB) { //------------------------------------------------------------------------- - // Test the rb_new functions + // Test the rb_node_new function //------------------------------------------------------------------------- TEST(Verify_rb_node_new_returns_a_new_node){ rb_node_t* node = rb_node_new(42); @@ -18,15 +18,32 @@ TEST_SUITE(RB) { CHECK(NULL == node->left); CHECK(NULL == node->right); CHECK(42 == node->contents); + CHECK(rb_node_is_valid(node, -1, -1)); mem_release(node); } + //------------------------------------------------------------------------- + // Test the rb_tree_new function + //------------------------------------------------------------------------- TEST(Verify_rb_tree_new_returns_an_empty_red_black_tree){ - rb_tree_t* rb = rb_tree_new(); - CHECK(rb != NULL); - CHECK(rb->root == NULL); - mem_release(rb); + rb_tree_t* tree = rb_tree_new(); + CHECK(NULL != tree); + CHECK(NULL == tree->root); + CHECK(rb_tree_is_valid(tree)); + mem_release(tree); } + //------------------------------------------------------------------------- + // Test insert functions + //------------------------------------------------------------------------- + TEST(Verify_rb_insert_to_an_empty_list_assigns_root){ + rb_tree_t* tree = rb_tree_new(); + rb_node_t* node = rb_tree_insert(tree, 42); + CHECK(NULL != node); + CHECK(tree->root == node); + CHECK(42 == node->contents); + CHECK(rb_tree_is_valid(tree)); + mem_release(tree); + } }