return (node ? node->color : BLACK);
}
-static void rb_tree_rotate_outside_left(rb_node_t* node){
+static void rb_tree_rotate_outside_left(rb_tree_t* tree, rb_node_t* node){
rb_node_t* parent = node->parent;
rb_node_t* grandparent = (parent ? parent->parent : NULL);
//rb_node_t* uncle = (grandparent ? (parent == grandparent->left ? grandparent->right : grandparent->left) : NULL);
grandparent->left = parent->right; //safe to overwrite gp->left. it is parent.
parent->right = grandparent;
grandparent->parent = parent;
+ //repair the tree root
+ if(tree->root == grandparent) tree->root = parent;
//repaint nodes as needed:
parent->color = BLACK;
grandparent->color = RED;
}
//mirror of above:
-static void rb_tree_rotate_outside_right(rb_node_t* node){
+static void rb_tree_rotate_outside_right(rb_tree_t* tree, rb_node_t* node){
rb_node_t* parent = node->parent;
rb_node_t* grandparent = (parent ? parent->parent : NULL);
//rb_node_t* uncle = (grandparent ? (parent == grandparent->left ? grandparent->right : grandparent->left) : NULL);
grandparent->right = parent->left; //safe to overwrite gp->right. it is parent.
parent->left = grandparent;
grandparent->parent = parent;
+ //repair the tree root
+ if(tree->root == grandparent) tree->root = parent;
//repaint nodes
parent->color = BLACK;
grandparent->color = RED;
}
//NODE:the node to be inserted
-static void rb_tree_recolor(rb_node_t* node){
+static void rb_tree_recolor(rb_tree_t* tree, rb_node_t* node){
rb_node_t* parent = node->parent;
rb_node_t* grandparent = (parent ? parent->parent : NULL);
rb_node_t* uncle = (grandparent ? (parent == grandparent->left ? grandparent->right : grandparent->left) : NULL);
grandparent->color = RED;
parent->color = BLACK;
uncle->color = BLACK;
- rb_tree_recolor(grandparent);
+ rb_tree_recolor(tree, grandparent);
}else if(node == parent->right && parent == grandparent->left){
//parent is red, uncle is black, "inside left" case
//first rotate node and parent
parent->parent = node;
parent->right = NULL;
//tree now transformed to an "outside left" case
- rb_tree_rotate_outside_left(parent);
+ rb_tree_rotate_outside_left(tree, parent);
}else if(node == parent->left && parent == grandparent->right){
//parent is red, uncle is black, "inside right" case
//first rotate node and parent
parent->parent = node;
parent->left = NULL;
//tree now transformed to an "outside right" case
- rb_tree_rotate_outside_right(parent);
+ rb_tree_rotate_outside_right(tree, parent);
}else if(node == parent->left && parent == grandparent->left){
//parent is red, uncle is black, "outside left" case
- rb_tree_rotate_outside_left(node);
+ rb_tree_rotate_outside_left(tree, node);
}else if(node == parent->right && parent == grandparent->right){
//parent is red, uncle is black, "outside right" case
- rb_tree_rotate_outside_right(node);
+ rb_tree_rotate_outside_right(tree, node);
}
}
static void rb_tree_insert_node(rb_tree_t* tree, rb_node_t* node, rb_node_t* parent){
if(NULL == parent){ /* inserting root of the tree */
tree->root = node;
- rb_tree_recolor(node);
+ rb_tree_recolor(tree, node);
}else if(node->contents < parent->contents){
if(parent->left){
rb_tree_insert_node(tree, node, parent->left);
}else{
node->parent = parent;
parent->left = node;
- rb_tree_recolor(node);
+ rb_tree_recolor(tree, node);
}
}else{
if(parent->right){
}else{
node->parent = parent;
parent->right = node;
- rb_tree_recolor(node);
+ rb_tree_recolor(tree, node);
}
}
}
CHECK(rb_tree_is_valid(tree));
mem_release(tree);
}
+ TEST(Verify_rb_insert_parent_uncle_mismatch_outside_left){
+ rb_tree_t* tree = rb_tree_new();
+ rb_node_t* node1 = rb_tree_insert(tree, 42);
+ rb_node_t* node2 = rb_tree_insert(tree, 32);
+ CHECK(RED == node2->color);
+ //tree->root->right == NULL ; black implicitly
+ rb_node_t* node3 = rb_tree_insert(tree, 15);
+ CHECK(node2 == tree->root);
+ //check node2 fields
+ CHECK(node3 == node2->left);
+ CHECK(node1 == node2->right);
+ CHECK(NULL == node2->parent)
+ CHECK(BLACK == node2->color);
+ CHECK(32 == node2->contents);
+ //check node1 fields
+ CHECK(NULL == node1->left);
+ CHECK(NULL == node1->right);
+ CHECK(node2 == node1->parent)
+ CHECK(RED == node1->color);
+ CHECK(42 == node1->contents);
+ //check node3 fields
+ CHECK(NULL == node3->left);
+ CHECK(NULL == node3->right);
+ CHECK(node2 == node3->parent);
+ CHECK(RED == node3->color);
+ CHECK(15 == node3->contents);
+ mem_release(tree);
+ }
}