#include <stdlib.h>
+#include <stdbool.h>
#include "mem.h"
#include "rb.h"
}
}
-
rb_node_t* rb_node_new(int contents){
rb_node_t* node = mem_allocate(sizeof(rb_node_t), &rb_node_free);
node->left = NULL;
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;
+}
+
extern "C" {
#endif
+#include <stdbool.h>
+
typedef enum {
RED = 0,
BLACK
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
}
//-----------------------------------------------------------------------------
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);
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);
+ }
}