how to fix this insertion function in red black tree implementation? - c

I'm implementing a red black tree i think there is something wrong with the fix up function, it doesn't insert the nodes as it should be done and gives me wrong height
i'm trying to insert a file in the tree and it gives me very large hight
typedef struct Node
{
char word[128];
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
struct Node T_Nil_Node;
Node* T_Nil = &T_Nil_Node;
struct Node* Root = NULL;
the rotate left function:
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right;
x->right = y->left;
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent;
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
the right rotate:
void rotateRight(Node** T, Node* y)
{
Node *x = y->left;
y->left = x->right;
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent;
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y;
y->parent = x;
}
the fixup function (i think there is something wrong here) :
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while (New->parent->color == RED )
{
if (New->parent == New->parent->parent->left)
temp = New->parent->parent->right;
else
temp = New ->parent->parent->left;
if (temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else if (New == New ->parent->right)
{
New = New->parent;
rotateLeft(Root, New);
New->parent= BLACK;
New->parent->parent=RED;
rotateRight(Root, New->parent->parent);
}
else
{
if (New->parent== New->parent->parent->right)
{
New = New->parent;
rotateRight(Root, New);
New->parent= BLACK;
New->parent->parent=RED;
rotateLeft(Root, New->parent->parent);
}
}
}
//Root[0]->color = BLACK;
(*Root)->color= BLACK;
}
insertion function which i think is right:
void redBlackInsert(Node** T, char word[128])
{
Node* z = newNode(word);
Node* y = T_Nil;
Node* x = *T;
while (x != T_Nil)
{
y = x;
if (strcmp(z->word,x->word)<0)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (strcmp(z->word,y->word)<0)
y->left = z;
else
y->right = z;
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
redBlackInsertFixup(T, z);
}

Related

Why do I have a red child from a red node in my Red Black Tree?

in my Red Black Tree I have red child from red node, what was wrong in my code?
The struct for RBTree:
num COLOR { RED, BLACK };
// struct RBT
typedef struct treeRBTnode {
int key;
enum COLOR color;
struct treeRBTnode* parent; // padre
struct treeRBTnode* left; // figlio sinistro
struct treeRBTnode* right; // figlio sinistro
} RBTNode;
typedef struct {
int cardinality;
struct treeRBTnode* root;
struct treeRBTnode* Nil;
} RBTree;
function to create a RBTree with T->Nil sentinel and create a new node:
//Initialize RBT
RBTree* InitializeRBT() {
RBTree* T = (RBTree*)malloc(sizeof(RBTree));
T->Nil = (RBTNode*)malloc(sizeof(RBTNode));
T->cardinality = 0;
T->Nil->left = T->Nil->right = T->Nil->parent = NULL;
T->Nil->color = BLACK;
T->Nil->key = 0;
T->root = T->Nil;
return T;
}
//Create a new Node;
//create a new node
RBTNode* RBTnewNode(int key) {
RBTNode* tmp = (RBTNode*)malloc(sizeof(RBTNode));
tmp->key = key;
tmp->color=RED;
tmp->left = tmp->right = NULL;
return tmp;
Now the insert algoritm with insertfixup, insertfixupleft and right, rotate left and right code:
void BSTreeRightRotate(RBTree* T, RBTNode* x) {
RBTNode* y = x->left;
x->left = y->right;
if (y->right != T->Nil)
y->right->parent = x;
y->parent = x->parent;
if (x->parent == T->Nil)
T->root = y;
if (x->parent != T->Nil && x == x->parent->left)
x->parent->left = y;
if (x->parent != T->Nil && x == x->parent->right)
x->parent->right = y;
y->right = x;
x->parent = y;
}
//the same for leftRotate but with left and right reversed
void RBTreeInsertFixupRight(RBTree* T, RBTNode* x) {
RBTNode* y = x->parent->parent->left;
if (y->color == RED) {
x->parent->color = BLACK;
y->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
} else {
if (x == x->parent->left) {
x = x->parent;
BSTreeRightRotate(T, x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
BSTreeLeftRotate(T, x->parent->parent);
}
}
//the same for fixupleft but with left and right reversed
void RBTreeInsertFixup(RBTree* T, RBTNode* x) {
while (x->parent->color == RED) {
if (x->parent == x->parent->parent->left)
RBTreeInsertFixupLeft(T, x);
else
RBTreeInsertFixupRight(T, x);
}
T->root->color = BLACK;
}
void RBTreeInsert(RBTree* T, RBTNode* x) {
RBTNode* y = T->Nil;
RBTNode* z = T->root;
while (z != T->Nil) {
y = z;
if (x->key < z->key)
z = z->left;
else
z = z->right;
}
x->parent = y;
if (y == T->Nil)
T->root = x;
if (y != T->Nil && x->key < y->key)
y->left = x;
if (y != T->Nil && x->key >= y->key)
y->right = x;
x->left = T->Nil;
x->right = T->Nil;
x->color = RED;
RBTreeInsertFixup(T, x);
}
Now after inserting elements in the tree through insert I realized that some red nodes sometimes have a red child, not respecting the validity of red blacks. I couldn't find the error in my code, could anyone help me?
This is wrong:
void RBTreeInsertFixupRight(RBTree* T, RBTNode* x) {
RBTNode* y = x->parent->parent->left;
if (y->color == RED) {
This assumes that y is a real node (the uncle) and it may not be. It may be NULL.
If it NULL => the color is automatically BLACK.
So the expression "y->color" may be dereferencing a NULL pointer.
The same issue applies to RBTreeInsertFixupLeft()

how i can get the height of a red black tree and not the black height

im trying to get the height of a red black tree that inserted in it a file of 3000+ word and it gives me a height = 1968 i dont know if the error in the insertion part or the algorithm of calculating the height
the function for height
#define MAX(a,b) (((a)>(b))?(a):(b))
int height(Node* Root)
{
int h = 0;
if (Root != NULL) {
if (Root == T_Nil)
h = 1;
else
{
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
h = MAX(leftHeight, rightHeight) + 1;
}
}
return h;
}
Having :
typedef struct Node {
char word[128];
char color;
struct Node * left;
struct Node *right;
struct Node *parent;
} Node;
struct Node T_Nil_Node;
Node * T_Nil = &T_Nil_Node;
insert function
void redBlackInsert(Node** T, char word[128])
{
Node* z = newNode(word);
Node* y = T_Nil;
Node* x = *T;
while (x != T_Nil)
{
y = x;
if (strcmp(z->word,x->word)<0)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (strcmp(z->word,y->word)<0)
y->left = z;
else
y->right = z;
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
redBlackInsertFixup(T, z);
}
fixup functin
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while (New->parent->color == RED)
{
if (New->parent == New->parent->parent->left)
{
temp = New->parent->parent->right;
if (temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else
{
if (New == New->parent->right)
{
New = New->parent;
rotateLeft(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateRight(Root, New->parent->parent);
}
}
else
{
temp = New->parent->parent->left;
if (temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else
{
if (New == New->parent->left)
{
New = New->parent;
rotateRight(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateLeft(Root, New->parent->parent);
}
}
}
Root[0]->color = BLACK;
}
rotating left
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right;
x->right = y->left;
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent;
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
rotating right (i use it in fix up)
void rotateRight(Node** T, Node* y)
{
Node *x = y->left;
y->left = x->right;
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent;
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y;
y->parent = x;
}
This line looks wrong
if (Root == T_Nil)
h = 1;
I'd expect it to look like this
if (Root->right == NULL && Root->left == NULL)
h = 1;
This is a node that has no children and thus has height of 1.
The function looks like it would work without this if statement since a null value to the function return 0. Since it already has the +1 after the MAX I'm guessing this is the more correct solution.
It seems you are mixing up NULL and a sentinel NIL node in your height function. Either you use NULL for representing "no childern" or you use a sentinel NIL object. Having both at the same time seems wrong.
Besides that it seems wrong to return 1 when a sentinel is reached.
Here is how I would expect the code to be...
Using sentinel NIL (which it seems you want to do)
int height(Node* Root)
{
assert(Root != NULL); // NULL is never allowed
if (Root == T_Nil) return 0; // No data here so return 0
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
int h = MAX(leftHeight, rightHeight) + 1;
return h;
}
Using NULL (which it seems you don't want to do)
int height(Node* Root)
{
if (Root == NULL) return 0; // No data here so return 0
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
int h = MAX(leftHeight, rightHeight) + 1;
return h;
}

Red Black Tree in C

I am trying to implement red black tree in C. For reference I am using CLRS.
But when I run the code I am getting "Segmentation fault (core dumped)" error message.
I can't figure out what's wrong in my code so, could anyone tell me what's wrong in my code?
The problem seems to be in the function rb_insert_fixup(), but I don't know what's wrong in it.
Code
#include <stdio.h>
#include <stdlib.h>
//constants
#define RED 0
#define BLACK 1
struct node
{
int key;
struct node *left;
struct node *right;
struct node *parent;
int color;
};
struct node *rb_insert(struct node *tree, struct node *z);
struct node *rb_insert_fixup(struct node *tree, struct node *z);
struct node *left_rotate(struct node *t, struct node *x);
struct node *right_rotate(struct node *t, struct node *x);
struct node *create_node(int key);
int main()
{
struct node *tree = NULL;
struct node *new;
new = create_node(5);
tree = rb_insert(tree, new);
new = create_node(15);
tree = rb_insert(tree, new);
new = create_node(4);
tree = rb_insert(tree, new);
new = create_node(14);
tree = rb_insert(tree, new);
printf("inserting 14\n");
printf("%d %d\n%d %d\n", (tree->left)->key, (tree->left)->color, ((tree->right)->left)->key, ((tree->right)->left)->color);
return 0;
}
struct node *rb_insert_fixup(struct node *tree, struct node *z)
{
struct node *y = NULL;
printf("fixup \n");
while ( z->parent != NULL && (z->parent)->color == RED )
{
printf("while\n");
if ( (z->parent)->parent != NULL && printf("if condition %d\n", (((z->parent)->parent)->left)->color) && z->parent == ((z->parent)->parent)->left )
{
printf("start if\n");
y = ((z->parent)->parent)->right;
if ( y->color == RED )
{
(z->parent)->color = BLACK;
y->color = BLACK;
((z->parent)->parent)->color = RED;
z = (z->parent)->parent;
}
else if ( z == (z->parent)->right )
{
z = z->parent;
tree = left_rotate(tree, z);
}
(z->parent)->color = BLACK;
((z->parent)->parent)->color = RED;
tree = right_rotate(tree, ((z->parent)->parent));
printf("End if\n");
}
else
{
y = ((z->parent)->parent)->left;
if ( y->color == RED )
{
(z->parent)->color = BLACK;
y->color = BLACK;
((z->parent)->parent)->color = RED;
z = (z->parent)->parent;
}
else if ( z == (z->parent)->left )
{
z = z->parent;
tree = right_rotate(tree, z);
}
(z->parent)->color = BLACK;
((z->parent)->parent)->color = RED;
tree = left_rotate(tree, ((z->parent)->parent));
printf("End else\n");
}
printf("End while\n");
}
tree->color = BLACK;
return tree;
}
struct node *rb_insert(struct node *tree, struct node *z)
{
struct node *y = NULL;
struct node *x = tree;
while (x != NULL)
{
y = x;
if (z->key < x->key)
{
x = x->left;
}
else
{
x = x->right;
}
}
z->parent = y;
if (y == NULL)
{
tree = z;
}
else if (z->key < y->key)
{
y->left = z;
}
else
{
y->right = z;
}
z->left = NULL;
z->right = NULL;
z->color = RED;
tree = rb_insert_fixup(tree, z);
//printf("bye insert\n");
return tree;
}
struct node *right_rotate(struct node *t, struct node *x)
{
struct node *y = x->left;
x->left = y->right;
if (y->right != NULL)
{
(y->right)->parent = x;
}
y->parent = x->parent;
if (x->parent == NULL)
{
t = y;
}
else if (x == (x->parent)->left)
{
(x->parent)->left = y;
}
else
{
(x->parent)->right = y;
}
y->right = x;
x->parent = y;
return t;
}
struct node *left_rotate(struct node *t, struct node *x)
{
struct node *y = x->right;
x->right = y->left;
if (y->left != NULL)
{
(y->left)->parent = x;
}
y->parent = x->parent;
if (x->parent == NULL)
{
t = y;
}
else if (x == (x->parent)->left)
{
(x->parent)->left = y;
}
else
{
(x->parent)->right = y;
}
y->left = x;
x->parent = y;
return t;
}
struct node *create_node(int key)
{
struct node *new = malloc(sizeof(struct node));
if (new == NULL)
{
fprintf(stderr, "Malloc failed to create a new node\n");
exit(EXIT_FAILURE);
}
else
{
new->key = key;
new->left = NULL;
new->right = NULL;
new->parent = NULL;
new->color = BLACK;
}
}
I have written the code wrong. After writing it again from scratch (using CLRS) and including sentinal node this time, everything is fine.
The rb_delete_fixup() function is as follows. The changes are in inner if-else. Similarly we have to change the inner if-else of rb_insert_fixup. It was a blunder to not write the correct code from the pseudocode.
Node *rb_delete_fixup(Node *tree, Node *tree_nil, Node *x)
{
Node *w;
while ( x != tree && x->color == BLACK )
{
if ( x == x->parent->left )
{
w = x->parent->right;
if ( w->color == RED )
{
w->color = BLACK;
x->parent->color = RED;
tree = left_rotate(tree, tree_nil, x->parent);
w = x->parent->right;
}
if ( w->left->color == BLACK && w->right->color == BLACK )
{
w->color = RED;
x = x->parent;
}
else
{
if ( w->right->color == BLACK )
{
w->left->color = BLACK;
w->color = RED;
tree = right_rotate(tree, tree_nil, w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->right->color = BLACK;
tree = left_rotate(tree, tree_nil, x->parent);
x = tree;
}
}
else
{
w = x->parent->left;
if ( w->color == RED )
{
w->color = BLACK;
x->parent->color = RED;
tree = right_rotate(tree, tree_nil, x->parent);
w = x->parent->left;
}
if ( w->left->color == BLACK && w->right->color == BLACK )
{
w->color = RED;
x = x->parent;
}
else
{
if ( w->left->color == BLACK )
{
w->right->color = BLACK;
w->color = RED;
tree = left_rotate(tree, tree_nil, w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
tree = right_rotate(tree, tree_nil, x->parent);
x = tree;
}
}
}
x->color = BLACK;
}

Trying to implement a red-black tree in C

I need help implementing a red-black tree It seems to keep seg faulting on my malloc calls. I am not sure how to fix it. Any advice would be greatly appreciated. The functions appear to be working the only issues i have are with allocating memory.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
Node **Root = NULL;
// A utility function to create a new BST node
Node *newNode(int data) {
Node *temp = (Node*)malloc(sizeof(Node));
temp->data = data;
temp->color = 'R';
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
return temp;
}
void rotateLeft(Node **Root, Node *New) {
Node *lPtr = New->right;
New->right = lPtr->left;
if (lPtr->left != NULL)
lPtr->left->parent = New;
lPtr->parent = New->parent;
if (New->parent == NULL)
*Root = lPtr;
else if (New->data == New->parent->left->data)
New->parent->left = lPtr;
else
New->parent->right = lPtr;
lPtr->left = New;
New->parent = lPtr;
}
void rotateRight (Node**Root, Node *New) {
Node *rPtr = New->left;
New->left = rPtr->right;
if (rPtr->right != NULL)
rPtr->right->parent = New;
rPtr->parent = New->parent;
if (New->parent == NULL)
*Root = rPtr;
else if (New->data == New->parent->left->data)
New->parent->left = rPtr;
else
New->parent->right = rPtr;
rPtr->right = New;
New->parent = rPtr;
}
void redBlackInsertFixup(Node **Root, Node *New) {
Node* temp;
while (New->parent->color == 'R') {
if (New->parent->data == New->parent->parent->data) {
temp = New->parent->parent->right;
if (temp->color == 'R') {
New->parent->color = 'B';
temp->color = 'B';
New->parent->parent->color = 'R';
New = New->parent->parent;
} else
if (New->data == New->parent->right->data) {
New = New->parent;
rotateLeft(Root,New);
}
New->parent->color = 'B';
New->parent->parent->color = 'R';
rotateRight(Root, New->parent->parent);
} else {
temp = New->parent->parent->left;
if (temp->color == 'R') {
New->parent->color = 'B';
New->color = 'B';
New->parent->parent->color = 'R';
New = New->parent->parent;
} else
if (New->data == New->parent->left->data) {
New = New->parent;
rotateRight(Root, New);
}
New->parent->color = 'B';
New->parent->parent->color = 'R';
rotateLeft(Root, New->parent->parent);
}
}
Root[0]->color = 'B';
}
void redBlackInsert(Node **Root, int data) {
Node *New = (Node *)malloc(sizeof(Node));
New->data = data;
New->left = NULL;
New->right = NULL;
New->color = 'R';
Node *Yp = NULL;
Node *Xp = *Root;
if (*Root != NULL) {
New->color = 'B';
*Root = New;
return;
}
while (Xp != NULL) {
Yp = Xp;
if (data < Xp->data)
Xp = Xp->left;
Xp = Xp->right;
}
New->parent = Yp;
if (Yp == NULL) {
*Root = New;
if (data < Yp->data)
Yp->left = New;
else
Yp->right = New;
}
New->left = NULL;
New->right = NULL;
New->color = 'R';
redBlackInsertFixup(Root, New);
}
void redBlackTreePrint(Node *Root) {
Node* temp = Root;
if (temp != NULL) {
redBlackTreePrint(temp->left);
printf(" %d - %c,", temp->data, temp->color == 'B' ? 'B' : 'R');
redBlackTreePrint(temp->right);
}
return;
}
int main(int argc, char *argv[]) {
redBlackInsert(Root, 7);
redBlackInsert(Root, 9);
redBlackTreePrint(*Root);
return 0;
}
Thanks!
Compile it with -g flags, and run with gdb, and you will find that it traps on line 120 at redBlackInsert because *Root is NULL.
scott > gcc -O0 -g redblack.c -o redblack
scott > redblack
Segmentation fault (core dumped)
scott > gdb redblack
(gdb) run
Starting program: /home/scott/stackOverflow/redblack/redblack
Program received signal SIGSEGV, Segmentation fault.
0x000000000040098c in redBlackInsert (Root=0x0, data=7) at redblack.c:120
120 Node* Xp = *Root;
(gdb) bt
#0 0x000000000040098c in redBlackInsert (Root=0x0, data=7) at redblack.c:120
#1 0x0000000000400af5 in main (argc=1, argv=0x7fffffffded8) at redblack.c:164
(gdb)
I modified the global Root to be "Node *Root" rather than "**Root" since this is more intuitive. Its three uses in main() had to be modified to match:
int main(int argc, char* argv[])
{
redBlackInsert(&Root, 7);
redBlackInsert(&Root, 9);
redBlackTreePrint(Root);
return 0;
}
On 138, you check if yp==NULL, then you dereference it which causes a segmentation fault on 139:
(gdb) run
Starting program: /home/scott/stackOverflow/redblack/redblack
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a0f in redBlackInsert (Root=0x601050 <Root>, data=7) at redblack.c:139
139 if(data < Yp->data)
(gdb) bt
#0 0x0000000000400a0f in redBlackInsert (Root=0x601050 <Root>, data=7) at redblack.c:139
#1 0x0000000000400af2 in main (argc=1, argv=0x7fffffffded8) at redblack.c:165
(gdb)
Sorry, that's as far as I got.
Here is my solution based on "Introduction to Algorithms", chapter 13 "Red-Black Trees", by Cormen, Leiserson, Rivest, Stein.
#include<stdio.h>
#include<stdlib.h>
#define RED 'R'
#define BLACK 'B'
typedef struct Node{
int key;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
// Based on CLRS algorithm, use T_Nil as a sentinel to simplify code
struct Node T_Nil_Node;
Node* T_Nil = &T_Nil_Node;
Node* Root = NULL;
// A utility function to create a new BST node
Node* newNode(int key)
{
Node *temp = (Node*) malloc(sizeof(Node));
temp->key = key;
temp->color = RED;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
return temp;
}
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right; // set y
x->right = y->left; // turn y's left subtree into x's right subtree{
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent; // link x's parent to y
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x; // put x on y's left
x->parent = y;
}
void rotateRight(Node** T, Node* y)
{
Node *x = y->left; // set x
y->left = x->right; // turn x's right subtree into y's left subtree{
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent; // link y's parent to x
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y; // put y on x's right
y->parent = x;
}
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while(New->parent->color == RED)
{
if(New->parent->key == New->parent->parent->key)
{
temp = New->parent->parent->right;
if(temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else if(New->key == New->parent->right->key)
{
New = New->parent;
rotateLeft(Root,New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateRight(Root,New->parent->parent);
}
else
{
temp = New->parent->parent->left;
if(temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else if(New->key == New->parent->left->key)
{
New = New->parent;
rotateRight(Root,New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateLeft(Root, New->parent->parent);
}
}
Root[0]->color = BLACK;
}
void redBlackInsert(Node** T, int key)
{
Node* z = newNode(key);
Node* y = T_Nil;
Node* x = *T;
// Find where to Insert new node Z into the binary search tree
while (x != T_Nil) {
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
// Init z as a red leaf
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
// Ensure the Red-Black property is maintained
redBlackInsertFixup(T,z);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
int height(Node* Root)
{
int h = 0;
if (Root != NULL) {
if (Root == T_Nil)
h = 1;
else
{
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
h = MAX(leftHeight, rightHeight) + 1;
}
}
return h;
}
int blackHeight(Node* Root)
{
int height = 0;
while (Root) {
if ((Root == T_Nil) || (Root->color == BLACK))
height++;
Root = Root->left;
}
return height;
}
void PrintHelper(Node* Root)
{
Node* temp = Root;
if (temp != NULL)
{
PrintHelper(temp->left);
printf(" %d%c(h=%d,bh=%d) ", temp->key, (temp->color == BLACK ? BLACK : RED), height(temp), blackHeight(temp));
PrintHelper(temp->right);
}
}
void redBlackTreePrint(Node* Root)
{
printf("Tree Height=%d, Black-Height=%d\n", height(Root), blackHeight(Root));
PrintHelper(Root);
printf("\n");
}
int main(int argc, char* argv[])
{
Node* Root = T_Nil;
redBlackInsert(&Root, 7);
redBlackInsert(&Root, 9);
redBlackTreePrint(Root);
}
Your bug appeared to be in redBlackInsert(). When I rewrote it, the segmentation faults disappeared. One thing to consider when fixing your code: use a sentinal node in your tree. This will simplify the logic around handling edge cases where you derefence null pointers. The CRLS textbook describes how this greatly simplifies Red-Black coding. Your bug may be related to mishandling edge cases.
Here is a sample run using your main():
scott > gcc -O0 -g redblack.c -o redblack
scott > redblack
Tree Height=3, Black-Height=2
0R(h=1,bh=1) 7B(h=3,bh=2) 0R(h=1,bh=1) 9R(h=2,bh=1) 0R(h=1,bh=1)
I modified readBlackTreePrint to display each node's height in the tree, and the each node's black-height (defined as the number of black nodes in its simple path to a leaf).
There are multiple problems in your code:
The global variable Root is a pointer to a pointer initialized to NULL: Node **Root = NULL;. This is not what redBlackInsert() expects: you should pass the address of the root node, which does not need to be a global variable:
int main(int argc, char *argv[]) {
Node *Root = NULL;
redBlackInsert(&Root, 7);
redBlackInsert(&Root, 9);
redBlackTreePrint(Root);
return 0;
}
You forget to initialize the parent member of the new node in redBlackInsert(). You should just use newNode():
Node *New = newNode(data);
The test for an empty tree in redBlackInsert() is incorrect: if (*Root != NULL) should be changed to:
if (*Root == NULL) {
New->color = 'B';
*Root = New;
return;
}
With these modifications, the program runs and outputs this:
7 - B,
which is incorrect but gives you a head start for where to look.
PanagiotisP is right, there are mistakes in ScottK's and cesign's code.
The corrected code is as follows:
#include<stdio.h>
#include<stdlib.h>
#define RED 'R'
#define BLACK 'B'
typedef struct Node{
int key;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
// Based on CLRS algorithm, use T_Nil as a sentinel to simplify code
struct Node T_Nil_Node;
Node* T_Nil = &T_Nil_Node;
Node* Root = NULL;
// A utility function to create a new BST node
Node* newNode(int key)
{
Node *temp = (Node*) malloc(sizeof(Node));
temp->key = key;
temp->color = RED;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
return temp;
}
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right; // set y
x->right = y->left; // turn y's left subtree into x's right subtree{
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent; // link x's parent to y
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x; // put x on y's left
x->parent = y;
}
void rotateRight(Node** T, Node* y)
{
Node *x = y->left; // set x
y->left = x->right; // turn x's right subtree into y's left subtree{
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent; // link y's parent to x
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y; // put y on x's right
y->parent = x;
}
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while(New->parent->color == RED)
{
if(New->parent->key == New->parent->parent->key)
{
temp = New->parent->parent->right;
if(temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else
{
if(New->key == New->parent->right->key)
{
New = New->parent;
rotateLeft(Root,New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateRight(Root,New->parent->parent);
}
}
else
{
temp = New->parent->parent->left;
if(temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else
{
if(New->key == New->parent->left->key)
{
New = New->parent;
rotateRight(Root,New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateLeft(Root, New->parent->parent);
}
}
}
Root[0]->color = BLACK;
}
void redBlackInsert(Node** T, int key)
{
Node* z = newNode(key);
Node* y = T_Nil;
Node* x = *T;
// Find where to Insert new node Z into the binary search tree
while (x != T_Nil) {
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
// Init z as a red leaf
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
// Ensure the Red-Black property is maintained
redBlackInsertFixup(T,z);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
int height(Node* Root)
{
int h = 0;
if (Root != NULL) {
if (Root == T_Nil)
h = 1;
else
{
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
h = MAX(leftHeight, rightHeight) + 1;
}
}
return h;
}
int blackHeight(Node* Root)
{
int height = 0;
while (Root) {
if ((Root == T_Nil) || (Root->color == BLACK))
height++;
Root = Root->left;
}
return height;
}
void PrintHelper(Node* Root)
{
Node* temp = Root;
if (temp != NULL)
{
PrintHelper(temp->left);
printf(" %d%c(h=%d,bh=%d) ", temp->key, (temp->color == BLACK ? BLACK : RED), height(temp), blackHeight(temp));
PrintHelper(temp->right);
}
}
void redBlackTreePrint(Node* Root)
{
printf("Tree Height=%d, Black-Height=%d\n", height(Root), blackHeight(Root));
PrintHelper(Root);
printf("\n");
}
int main(int argc, char* argv[])
{
Node* Root = T_Nil;
redBlackInsert(&Root, 7);
redBlackInsert(&Root, 6);
redBlackInsert(&Root, 9);
redBlackInsert(&Root, 8);
redBlackTreePrint(Root);
}
The code of ScottK has little problem, I changed as blow:
#include<stdio.h>
#include<stdlib.h>
#define RED 'R'
#define BLACK 'B'
typedef struct Node {
int key;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
// Based on CLRS algorithm, use T_Nil as a sentinel to simplify code
struct Node T_Nil_Node;
Node* T_Nil = &T_Nil_Node;
Node* Root = NULL;
// A utility function to create a new BST node
Node* newNode(int key)
{
Node *temp = (Node*) malloc(sizeof(Node));
temp->key = key;
temp->color = RED;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
return temp;
}
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right; // set y
x->right = y->left; // turn y's left subtree into x's right subtree{
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent; // link x's parent to y
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x; // put x on y's left
x->parent = y;
}
void rotateRight(Node** T, Node* y)
{
Node *x = y->left; // set x
y->left = x->right; // turn x's right subtree into y's left subtree{
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent; // link y's parent to x
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y; // put y on x's right
y->parent = x;
}
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while (New->parent->color == RED)
{
if (New->parent == New->parent->parent->left)
{
temp = New->parent->parent->right;
if (temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else {
if (New == New->parent->right)
{
New = New->parent;
rotateLeft(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateRight(Root, New->parent->parent);
}
}
else
{
temp = New->parent->parent->left;
if (temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else {
if (New == New->parent->left)
{
New = New->parent;
rotateRight(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateLeft(Root, New->parent->parent);
}
}
}
Root[0]->color = BLACK;
}
void redBlackInsert(Node** T, int key)
{
Node* z = newNode(key);
Node* y = T_Nil;
Node* x = *T;
// Find where to Insert new node Z into the binary search tree
while (x != T_Nil) {
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
// Init z as a red leaf
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
// Ensure the Red-Black property is maintained
redBlackInsertFixup(T, z);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
int height(Node* Root)
{
int h = 0;
if (Root != NULL) {
if (Root == T_Nil)
h = 1;
else
{
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
h = MAX(leftHeight, rightHeight) + 1;
}
}
return h;
}
//中序遍历
void printTree(Node* root)
{
if (root->left != T_Nil)
printTree(root->left);
printf("%d ", root->key);
if (root->right != T_Nil)
printTree(root->right);
}
int main(int argc, char* argv[])
{
Node* Root = T_Nil;
int list[10] = {1, 3, 2, 5, 4, 7, 6, 9, 8, 10};
for (int i = 0; i < 10; i++)
{
//printf("%d ", list[i]);
redBlackInsert(&Root, list[i]);
}
printTree(Root);
}
I noticed a mistake in ScottK's and cesign's code.
In the redBlackInsertFixup function inside the following if statement:
Wrong Code
if (temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
Corrected Code
if (temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
as you can see the following line has changed:
temp->color = BLACK; // Error: New->color = BLACK;
The error with this line can be seen when we insert the elements {7, 6, 9, 8} in this order. The resulting tree the previous code was producing:
7(B)
______|______
| |
6(R) 9(B)
___|___ ___|___
| | | |
T_NIL T_NIL 8(B) T_NIL
as you can see the property of the red-black tree, that any path from one node must have the same number of black nodes, is not maintained as there are two more black (B) nodes on the right path from the root than on the left path.
With the new code the resulting tree is:
7(B)
______|______
| |
6(B) 9(B)
___|___ ___|___
| | | |
T_NIL T_NIL 8(R) T_NIL
Which maintains all the red-black tree properties.
Note:
I can't comment on ScottK's or cesign's answer because commenting on StackOverflow requires reputation >= 50.

Segmentation Fault in a Simple Red-Black Tree

I'm trying to build a simple red-black tree in C. Unfortunately, I have encountered a segmentation fault that I'm not sure how to fix. I've included the code below and marked to line where the fault is occurring.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define RED 1
#define BLACK 0
typedef struct RBNode {
char key[50];
int color;
struct RBNode *left;
struct RBNode *right;
struct RBNode *parent;
} RBNode;
typedef struct RBTree {
struct RBNode *root;
struct RBNode *nil;
} RBTree;
void inorderPrint(RBTree*, RBNode*);
void insertRB(RBTree*, RBNode*);
void insertRBFixup(RBTree*, RBNode*);
void leftRotate(RBTree*, RBNode*);
void rightRotate(RBTree*, RBNode*);
int count;
int main (int argc, char* argv[]) {
RBTree *tree = malloc(sizeof(RBTree));
tree->nil = malloc(sizeof(RBNode));
tree->nil->color = BLACK;
tree->root = NULL;
tree->nil->left = tree->root;
tree->nil->right = tree->root;
RBNode *curr = NULL;
curr = malloc(sizeof(RBNode));
strcpy(curr->key, "CAT");
insertRB(tree, curr);
strcpy(curr->key, "HAT");
insertRB(tree, curr);
strcpy(curr->key, "BIT");
insertRB(tree, curr);
strcpy(curr->key, "CAR");
insertRB(tree, curr);
strcpy(curr->key, "MAP");
insertRB(tree, curr);
inorderPrint(tree, tree->root);
return 1;
}
void inorderPrint(RBTree* tree, RBNode *node) {
if ((node != NULL) && (node != tree->nil)) {
inorderPrint(tree, node->left);
printf("%s\n", node->key);
inorderPrint(tree, node->right);
}
}
void leftRotate(RBTree *tree, RBNode *x) {
struct RBNode *y = NULL;
y = x->right;
x->right = y->left;
if (y->left != tree->nil) {
y->left->parent = x; //Segmentation fault occurs here
}
y->parent = x->parent;
if (x->parent == tree->nil) {
tree->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
}
y->left = x;
x->parent = y;
}
void rightRotate(RBTree *tree, RBNode *x) {
RBNode *y = x->left;
x->left = y->right;
if (y->right != tree->nil) {
y->right->parent = x;
}
y->parent = x->parent;
if (x->parent == tree->nil) {
tree->root = y;
} else if (x == x->parent->right) {
x->parent->right = y;
} else {
x->parent->left = y;
}
y->right = x;
x->parent = y;
}
void insertRB(RBTree *tree, RBNode *z) {
RBNode *y = tree->nil;
RBNode *x = tree->root;
while ((x != tree->nil) && (x != NULL)) {
y = x;
if (strcmp(z->key, x->key) < 0) {
x = x->left;
} else {
x = x->right;
}
}
z->parent = y;
if (y == tree->nil) {
tree->root = z;
} else if (strcmp(z->key, y->key) < 0) {
y->left = z;
} else {
y->right = z;
}
z->left = tree->nil;
z->right = tree->nil;
z->color = RED;
insertRBFixup(tree, z);
}
void insertRBFixup(RBTree *tree, RBNode *z) {
RBNode *y = NULL;
while (z->parent->color == RED) {
if (z->parent == z->parent->parent->left) {
y = z->parent->parent->right;
if (y->color == RED) {
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
} else if (z == z->parent->right) {
z = z->parent;
leftRotate(tree, z);
} else {
z->parent->color = BLACK;
z->parent->parent->color = RED;
rightRotate(tree, z->parent->parent);
}
} else {
y = z->parent->parent->left;
if (y->color == RED) {
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
} else if (z == z->parent->left) {
z = z->parent;
rightRotate(tree, z);
} else {
z->parent->color = BLACK;
z->parent->parent->color = RED;
leftRotate(tree, z->parent->parent);
}
}
}
tree->root->color = BLACK;
}
I think it might have something to do with how I initialized the red-black tree in main(), but I'm not sure and I've tried many different other ways to initialize it.
Do any of you guys know where I'm going wrong?
In
if (y->left != tree->nil) {
y->left->parent = x; //Segmentation fault occurs here
}
y->left can be NULL.
leftRotate need to check for NULL pointers

Resources