Skip to main content

C Program To Implement Red Black Tree Operations.

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.

coloring and rotation 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

y is red and z is a left child

ĂĽ  Case 2: y is red and z is a right child

y is red and z is a right child

ĂĽ  Case 3: y is black and z is a left child

y is black and z is a left child

ĂĽ  Case 4: y is black and z is a right child

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

w is red

ĂĽ  Case 2: w is black; both w’s children are black

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

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

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;
}

Popular posts from this blog

Introduction To Algorithms, 3rd Edition

Before there were computers, there were algorithms. But now that there are computers, there are even more algorithms, and algorithms lie at the heart of computing. This book provides a comprehensive introduction to the modern study of computer algorithms. It presents many algorithms and covers them in considerable depth, yet makes their design and analysis accessible to all levels of readers. In this book, the authors tried to keep explanations elementary without sacrificing depth of coverage or mathematical rigor. Each chapter presents an algorithm, a design technique, an application area, or a related topic. Algorithms are described in English and in a pseudocode designed to be readable by anyone who has done a little programming. The book contains 244 figures — many with multiple parts — illustrating how the algorithms work. It also includes careful analysis of the running times of all algorithms. In this third edition, the entire book once again updated including changes cove...

C Program To Check Whether A Number Is Palindrome Or Not.

This program takes an integer from user and the integer is reversed. If the reversed integer is equal to the integer entered by user then that number is a palindrome. If not that number is not a palindrome.   #include <stdio.h> int main()  { int num, temp, remainder, reverse = 0; printf("Enter an integer: "); scanf("%d", &num); /*  original number is stored at temp */ temp = num; while (num > 0)  { remainder = num % 10; reverse = reverse * 10 + remainder; num /= 10;   }

The Basics Of C Programming - Part 3.

There are a number of different C input commands, the most useful of which is the scanf command. To read a single integer value into the variable called a you can use: scanf("%d",&a); When the program reaches the scanf statement it pauses to give the user time to type something on the keyboard and continues only when users press Enter or Return, to signal that he, or she, has finished entering the value. Then the program continues with the new value stored in a. In this way, each time the program is run the user gets a chance to type in a different value to the variable and the program also gets the chance to produce a different result! The final missing piece in the jigsaw is using the printf function, the one we use to print the value currently being stored in a variable. To display the value stored in the variable a you can use: printf("The value stored in a is %d",a); Note: the scanf function does not prompt for an input. You should ge...

C++ Program To Implement Bank Management System.

#include<iostream> #include<fstream> #include<cctype> #include<iomanip> #include <cstdlib> using namespace std; class account { int acno; char name[50]; int deposit; char type; public: void create_account(); //function to get data from user void show_account() const; //function to show data on screen void modify(); //function to add new data void dep(int); //function to accept amount and add to balance amount void draw(int); //function to accept amount and subtract from balance amount void report() const; //function to show data in tabular format int retacno() const; //function to return account number int retdeposit() const; //function to return balance amount char rettype() const;  //function to return type of account }; void account::create_account() { cout<<"\nEnter The Account No. : "; cin>>acno; cout<<"\n\nEnter The Name Of The Account Holder : "; cin.ig...