]> git.mdlowis.com Git - projs/libcds.git/commitdiff
red/black check functions
authora bellenir <a@bellenir.com>
Tue, 5 Aug 2014 20:52:01 +0000 (20:52 +0000)
committera bellenir <a@bellenir.com>
Tue, 5 Aug 2014 20:52:01 +0000 (20:52 +0000)
source/rb/rb.c
source/rb/rb.h
tests/test_rb.c

index 07de5f368ba38950e43b1b80a7bd6166040c654a..9fa7ed3c7cddad79d6e545b6e469d635e6607d64 100644 (file)
@@ -1,4 +1,5 @@
 #include <stdlib.h>
+#include <stdbool.h>
 
 #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;
+}
+
index 06dd29378439a62779717705ffad3f4fa33b1269..73421d9a4b2873d49900fb98bebcc4619c6762d8 100644 (file)
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
+
 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
 }
index e2440c63ef02795bca09157af6c60cde4fb68467..3b75bce36baa675651ea8c83a9a22655ae5651d2 100644 (file)
@@ -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);
+    }
 }