A red–black tree is a self-balancing
binary search tree which supports the operation search, find predecessor, find
successor, find minimum, find maximum, insertion and deletion in O(log n)-time.
In addition to the requirements imposed on a binary search tree, the following
must be satisfied to be a red–black tree:
1) A node is
either red or black.
2) The root is
black.
3) All leaves
(NIL) are black.
4) If a node is
red, then both its children are black.
5) Every path
from a given node to any of its descendant NIL nodes contains the same number
of black nodes.
If there is a modification in RB tree due
to insertion or deletion of any element, the new tree is then rearranged and
repainted to restore the properties.
Suppose insert a node z in any RB tree; at first set the color of z to red.
Now there are several cases we have to consider to keep the tree balanced:
ü
Case
1: y is red and z is a left child
ü
Case
2: y is red and z is a right child
ü
Case
3: y is black and z is a left child
ü
Case
4: y is black and z is a right child
Suppose we need to delete node z from the RB tree. If z is
red, it doesn’t violate any property. If z is a leaf, it also doesn’t violate
any property. Otherwise z is black and has a child; it violates property 2, 4,
and 5. For property 2, set the color of root to black after deletion.
To fix property 4 and 5:
ü
If
z's child x (which is the replacing node) is red, set x to black. Done!
ü
If
x is black, add another black to x, so that x will be a doubly black node, and
property 4 and 5 are fixed. But property 1 is violated.
To fix property 1, we must consider whether
ü
x
is a left child or right child.
ü
The
color of x's sibling w is red or black.
ü
The
colors of w's children.
Let x is a left child; the other case
can be done by symmetric operation. Now there are several cases we need to consider
to keep the tree balanced:
ü
Case
1: w is red
ü
Case
2: w is black; both w’s children are black
ü
Case
3: w is black, w’s left child is red, w’s right child is black
ü
Case
4: w is black; w’s right child is red
Source
Code of RB Tree:
#include <stdio.h>
#include <stdlib.h>
enum nodeColor { RED, BLACK };
struct rbNode {
int data, color;
struct rbNode *link[2];
};
struct rbNode *root = NULL;
struct rbNode * createNode(int data) {
struct rbNode *newnode;
newnode = (struct rbNode
*)malloc(sizeof(struct rbNode));
newnode->data = data;
newnode->color = RED;
newnode->link[0] =
newnode->link[1] = NULL;
return newnode;
}
void insertion (int data) {
struct rbNode *stack[98], *ptr,
*newnode, *xPtr, *yPtr;
int dir[98], ht = 0, index;
ptr = root;
if (!root) {
root = createNode(data);
return;
}
stack[ht] = root;
dir[ht++] = 0;
// find the place to insert the new
node
while (ptr != NULL) {
if (ptr->data == data) {
printf("\nDUPLICATES NOT
ALLOWED.\n");
return;
}
index = (data - ptr->data) > 0 ?
1 : 0;
stack[ht] = ptr;
ptr = ptr->link[index];
dir[ht++] = index;
}
// insert the new node
stack[ht - 1]->link[index] =
newnode = createNode(data);
while ((ht >= 3) &&
(stack[ht - 1]->color == RED)) {
if (dir[ht - 2] == 0) {
yPtr = stack[ht - 2]->link[1];
if (yPtr != NULL &&
yPtr->color == RED) {
stack[ht - 2]->color = RED;
stack[ht - 1]->color =
yPtr->color = BLACK;
ht = ht -2;
}
else {
if (dir[ht - 1] == 0) {
yPtr = stack[ht - 1];
}
else {
xPtr = stack[ht - 1];
yPtr = xPtr->link[1];
xPtr->link[1] = yPtr->link[0];
yPtr->link[0] = xPtr;
stack[ht - 2]->link[0] = yPtr;
}
xPtr = stack[ht - 2];
xPtr->color = RED;
yPtr->color = BLACK;
xPtr->link[0] = yPtr->link[1];
yPtr->link[1] = xPtr;
if (xPtr == root) {
root = yPtr;
}
else {
stack[ht - 3]->link[dir[ht - 3]] =
yPtr;
}
break;
}}
else {
yPtr = stack[ht - 2]->link[0];
if ((yPtr != NULL) &&
(yPtr->color == RED)) {
stack[ht - 2]->color = RED;
stack[ht - 1]->color =
yPtr->color = BLACK;
ht = ht - 2;
}
else {
if (dir[ht - 1] == 1) {
yPtr = stack[ht - 1];
}
else {
xPtr = stack[ht - 1];
yPtr = xPtr->link[0];
xPtr->link[0] = yPtr->link[1];
yPtr->link[1] = xPtr;
stack[ht - 2]->link[1] = yPtr;
}
xPtr = stack[ht - 2];
yPtr->color = BLACK;
xPtr->color = RED;
xPtr->link[1] = yPtr->link[0];
yPtr->link[0] = xPtr;
if (xPtr == root) {
root = yPtr;
}
else {
stack[ht - 3]->link[dir[ht - 3]] =
yPtr;
}
break;
}}}
root->color = BLACK;
}
void deletion(int data) {
struct rbNode *stack[98], *ptr, *xPtr,
*yPtr;
struct rbNode *pPtr, *qPtr, *rPtr;
int dir[98], ht = 0, diff, i;
enum nodeColor color;
if (!root) {
printf("\nGIVEN DATA NOT
FOUND.\n");
return;
}
ptr = root;
// search the node to delete
while (ptr != NULL) {
if ((data - ptr->data) == 0)
break;
diff = (data - ptr->data) > 0 ?
1 : 0;
stack[ht] = ptr;
dir[ht++] = diff;
ptr = ptr->link[diff];
}
if (ptr->link[1] == NULL) {
// node with no children
if ((ptr == root) &&
(ptr->link[0] == NULL)) {
free(ptr);
root = NULL;
}
// deleting root with one child
else if (ptr == root) {
root = ptr->link[0];
free(ptr);
}
else {
// node with one child
stack[ht - 1]->link[dir[ht - 1]] =
ptr->link[0];
}}
else {
xPtr = ptr->link[1];
if (xPtr->link[0] == NULL) {
xPtr->link[0] = ptr->link[0];
color = xPtr->color;
xPtr->color = ptr->color;
ptr->color = color;
if (ptr == root) {
root = xPtr;
}
else {
stack[ht - 1]->link[dir[ht - 1]] =
xPtr;
}
dir[ht] = 1;
stack[ht++] = xPtr;
}
// deleting node with 2 children
else {
i = ht++;
while (1) {
dir[ht] = 0;
stack[ht++] = xPtr;
yPtr = xPtr->link[0];
if (!yPtr->link[0])
break;
xPtr = yPtr;
}
dir[i] = 1;
stack[i] = yPtr;
if (i > 0)
stack[i - 1]->link[dir[i - 1]] =
yPtr;
yPtr->link[0] = ptr->link[0];
xPtr->link[0] = yPtr->link[1];
yPtr->link[1] = ptr->link[1];
if (ptr == root) {
root = yPtr;
}
color = yPtr->color;
yPtr->color = ptr->color;
ptr->color = color;
}}
if (ht < 1)
return;
if (ptr->color == BLACK) {
while (1) {
pPtr = stack[ht - 1]->link[dir[ht -
1]];
if (pPtr && pPtr->color ==
RED) {
pPtr->color = BLACK;
break;
}
if (ht < 2)
break;
if (dir[ht - 2] == 0) {
rPtr = stack[ht - 1]->link[1];
if (!rPtr)
break;
if (rPtr->color == RED) {
stack[ht - 1]->color = RED;
rPtr->color = BLACK;
stack[ht - 1]->link[1] =
rPtr->link[0];
rPtr->link[0] = stack[ht - 1];
if (stack[ht - 1] == root) {
root = rPtr;
}
else {
stack[ht - 2]->link[dir[ht - 2]] =
rPtr;
}
dir[ht] = 0;
stack[ht] = stack[ht - 1];
stack[ht - 1] = rPtr;
ht++;
rPtr = stack[ht - 1]->link[1];
}
if ( (!rPtr->link[0] ||
rPtr->link[0]->color == BLACK) &&
(!rPtr->link[1] ||
rPtr->link[1]->color == BLACK)) {
rPtr->color = RED;
}
else {
if (!rPtr->link[1] ||
rPtr->link[1]->color == BLACK) {
qPtr = rPtr->link[0];
rPtr->color = RED;
qPtr->color = BLACK;
rPtr->link[0] = qPtr->link[1];
qPtr->link[1] = rPtr;
rPtr = stack[ht - 1]->link[1] =
qPtr;
}
rPtr->color = stack[ht -
1]->color;
stack[ht - 1]->color = BLACK;
rPtr->link[1]->color = BLACK;
stack[ht - 1]->link[1] = rPtr->link[0];
rPtr->link[0] = stack[ht - 1];
if (stack[ht - 1] == root) {
root = rPtr;
}
else {
stack[ht - 2]->link[dir[ht - 2]] =
rPtr;
}
break;
}}
else {
rPtr = stack[ht - 1]->link[0];
if (!rPtr)
break;
if (rPtr->color == RED) {
stack[ht - 1]->color = RED;
rPtr->color = BLACK;
stack[ht - 1]->link[0] =
rPtr->link[1];
rPtr->link[1] = stack[ht - 1];
if (stack[ht - 1] == root) {
root = rPtr;
}
else {
stack[ht - 2]->link[dir[ht - 2]] =
rPtr;
}
dir[ht] = 1;
stack[ht] = stack[ht - 1];
stack[ht - 1] = rPtr;
ht++;
rPtr = stack[ht - 1]->link[0];
}
if ( (!rPtr->link[0] ||
rPtr->link[0]->color == BLACK) &&
(!rPtr->link[1] ||
rPtr->link[1]->color == BLACK)) {
rPtr->color = RED;
}
else {
if (!rPtr->link[0] ||
rPtr->link[0]->color == BLACK) {
qPtr = rPtr->link[1];
rPtr->color = RED;
qPtr->color = BLACK;
rPtr->link[1] = qPtr->link[0];
qPtr->link[0] = rPtr;
rPtr = stack[ht - 1]->link[0] =
qPtr;
}
rPtr->color = stack[ht -
1]->color;
stack[ht - 1]->color = BLACK;
rPtr->link[0]->color = BLACK;
stack[ht - 1]->link[0] =
rPtr->link[1];
rPtr->link[1] = stack[ht - 1];
if (stack[ht - 1] == root) {
root = rPtr;
}
else {
stack[ht - 2]->link[dir[ht - 2]] =
rPtr;
}
break;
}}
ht--;
return;
}}}
void searchElement(int data) {
struct rbNode *temp = root;
int diff;
while (temp != NULL) {
diff = data - temp->data;
if (diff > 0) {
temp = temp->link[1];
}
else if (diff < 0) {
temp = temp->link[0];
}
else {
printf("\nGIVEN DATA WAS FOUND IN
RB TREE.\n");
return;
}}
printf("\nGIVEN DATA WAS NOT
FOUND IN RB TREE.\n");
return;
}
void inorderTraversal(struct rbNode
*node) {
if (node) {
inorderTraversal(node->link[0]);
printf("%d ",
node->data);
inorderTraversal(node->link[1]);
return;
}}
int main() {
int ch, data;
while (1) {
printf("\t(1) INSERTION\t(2)
DELETION\n");
printf("\t(3) SEARCH\t(4)
DISPLAY\n");
printf("\t(5) EXIT \n\nENTER YOUR
CHOICE: ");
scanf("%d", &ch);
switch (ch) {
case 1:
printf("\nENTER THE DATA TO
INSERT: ");
scanf("%d", &data);
insertion(data);
break;
case 2:
printf("\nENTER THE DATA TO
DELETE: ");
scanf("%d", &data);
deletion(data);
break;
case 3:
printf("\nENTER THE SEARCH
ELEMENT: ");
scanf("%d", &data);
searchElement(data);
break;
case 4:
printf("\nINORDER TRAVERSAL OF RB
TREE: ");
inorderTraversal(root);
printf("\n");
break;
case 5:
exit(0);
default:
printf("\nYOU HAVE ENTERED WRONG
OPTION.\n");
break;
}
printf("\n");
}
return 0;
}