Skip to content

Instantly share code, notes, and snippets.

@SubCoder1
Created August 22, 2018 17:26
Show Gist options
  • Save SubCoder1/70c2cedc44353ffc539c7567b1051028 to your computer and use it in GitHub Desktop.
Save SubCoder1/70c2cedc44353ffc539c7567b1051028 to your computer and use it in GitHub Desktop.
Red Black Tree implementation in C++
#include <bits/stdc++.h>
using namespace std;
struct node {
int data{};
node* left = nullptr;
node* right = nullptr;
node* parent = nullptr;
string color;
};
class RB_TREE {
node* root;
public:
RB_TREE() : root(nullptr) {}
node* GetRoot(){ return root; }
void InsertNode(int stuff) {
if(root == nullptr){
root = new node();
root->data = stuff;
root->parent = nullptr;
root->color = "BLACK";
cout << "Element inserted.\n";
}
else {
auto linker = GetRoot();
node* newnode = new node();
newnode->data = stuff;
while(linker != nullptr){
if(linker->data > stuff){
if(linker->left == nullptr){
linker->left = newnode;
newnode->color = "RED";
newnode->parent = linker;
cout << "Element inserted.\n"; break; }
else { linker = linker->left; }
} else {
if(linker->right == nullptr){
linker->right = newnode;
newnode->color = "RED";
newnode->parent = linker;
cout << "Element inserted.\n"; break; }
else { linker = linker->right; }
}
}
RB_Insert_Fixup(newnode);
}
}
void RB_Insert_Fixup(node* z) {
while(z->parent->color == "RED") {
auto grandparent = z->parent->parent;
auto uncle = GetRoot();
if(z->parent == grandparent->left) {
if(grandparent->right) { uncle = grandparent->right; }
if(uncle->color == "RED"){
z->parent->color = "BLACK";
uncle->color = "BLACK";
grandparent->color = "RED";
if(grandparent->data != root->data){ z = grandparent; }
else { break; }
}
else if(z == grandparent->left->right) {
LeftRotate(z->parent);
}
else {
z->parent->color = "BLACK";
grandparent->color = "RED";
RightRotate(grandparent);
if(grandparent->data != root->data){ z = grandparent; }
else { break; }
}
}
else {
if(grandparent->left) { uncle = grandparent->left; }
if(uncle->color == "RED"){
z->parent->color = "BLACK";
uncle->color = "BLACK";
grandparent->color = "RED";
if(grandparent->data != root->data){ z = grandparent; }
else { break; }
}
else if(z == grandparent->right->left){
RightRotate(z->parent);
}
else {
z->parent->color = "BLACK";
grandparent->color = "RED";
LeftRotate(grandparent);
if(grandparent->data != root->data){ z = grandparent; }
else { break; }
}
}
}
root->color = "BLACK";
}
void RemoveNode(node* parent, node* curr, int stuff) {
if(curr == nullptr) { return; }
if(curr->data == stuff) {
//CASE -- 1
if(curr->left == nullptr && curr->right == nullptr) {
if(parent->data == curr->data){ root = nullptr; }
else if(parent->right == curr) {
RB_Delete_Fixup(curr);
parent->right = nullptr;
}
else {
RB_Delete_Fixup(curr);
parent->left = nullptr;
}
}
//CASE -- 2
else if(curr->left != nullptr && curr->right == nullptr) {
int swap = curr->data;
curr->data = curr->left->data;
curr->left->data = swap;
RemoveNode(curr, curr->right, stuff);
}
else if(curr->left == nullptr && curr->right != nullptr) {
int swap = curr->data;
curr->data = curr->right->data;
curr->right->data = swap;
RemoveNode(curr, curr->right, stuff);
}
//CASE -- 3
else {
bool flag = false;
node* temp = curr->right;
while(temp->left) { flag = true; parent = temp; temp = temp->left; }
if(!flag) { parent = curr; }
int swap = curr->data;
curr->data = temp->data;
temp->data = swap;
RemoveNode(parent, temp, swap);
}
}
}
void Remove(int stuff) {
auto temp = root;
auto parent = temp;
bool flag = false;
if(!temp) { RemoveNode(nullptr, nullptr, stuff); }
while(temp) {
if(stuff == temp->data) { flag = true; RemoveNode(parent, temp, stuff); break; }
else if(stuff < temp->data) { parent = temp ; temp = temp->left; }
else { parent = temp ; temp = temp->right; }
}
if(!flag) { cout << "\nElement doesn't exist in the table"; }
}
void RB_Delete_Fixup(node* z) {
while(z->data != root->data && z->color == "BLACK") {
auto sibling = GetRoot();
if(z->parent->left == z) {
if(z->parent->right){ sibling = z->parent->right; }
if(sibling) {
//CASE -- 1
if(sibling->color == "RED") {
sibling->color = "BLACK";
z->parent->color = "RED";
LeftRotate(z->parent);
sibling = z->parent->right;
}
//CASE -- 2
if(sibling->left == nullptr && sibling->right == nullptr) {
sibling->color = "RED";
z = z->parent;
}
else if(sibling->left->color == "BLACK" && sibling->right->color == "BLACK") {
sibling->color = "RED";
z = z->parent;
}
//CASE -- 3
else if(sibling->right->color == "BLACK") {
sibling->left->color = "BLACK";
sibling->color = "RED";
RightRotate(sibling);
sibling = z->parent->right;
} else {
sibling->color = z->parent->color;
z->parent->color = "BLACK";
if(sibling->right){ sibling->right->color = "BLACK"; }
LeftRotate(z->parent);
z = root;
}
}
} else {
if(z->parent->right == z){
if(z->parent->left){ sibling = z->parent->left; }
if(sibling) {
//CASE -- 1
if(sibling->color == "RED"){
sibling->color = "BLACK";
z->parent->color = "RED";
RightRotate(z->parent);
sibling = z->parent->left;
}
//CASE -- 2
if(sibling->left == nullptr && sibling->right == nullptr) {
sibling->color = "RED";
z = z->parent;
}
else if(sibling->left->color == "BLACK" && sibling->right->color == "BLACK") {
sibling->color = "RED";
z = z->parent;
}
//CASE -- 3
else if(sibling->left->color == "BLACK") {
sibling->right->color = "BLACK";
sibling->color = "RED";
RightRotate(sibling);
sibling = z->parent->left;
} else {
sibling->color = z->parent->color;
z->parent->color = "BLACK";
if(sibling->left){ sibling->left->color = "BLACK"; }
LeftRotate(z->parent);
z = root;
}
}
}
}
}
z->color = "BLACK";
}
node* TreeSearch(int stuff) {
auto temp = GetRoot();
if(temp == nullptr) { return nullptr; }
while(temp) {
if(stuff == temp->data){ return temp; }
else if(stuff < temp->data){ temp = temp->left; }
else { temp = temp->right; }
}
return nullptr;
}
void LeftRotate(node* x) {
node* nw_node = new node();
if(x->right->left) { nw_node->right = x->right->left; }
nw_node->left = x->left;
nw_node->data = x->data;
nw_node->color = x->color;
x->data = x->right->data;
x->left = nw_node;
if(nw_node->left){ nw_node->left->parent = nw_node; }
if(nw_node->right){ nw_node->right->parent = nw_node; }
nw_node->parent = x;
if(x->right->right){ x->right = x->right->right; }
else { x->right = nullptr; }
if(x->right){ x->right->parent = x; }
}
void RightRotate(node* x) {
node* nw_node = new node();
if(x->left->right){ nw_node->left = x->left->right; }
nw_node->right = x->right;
nw_node->data = x->data;
nw_node->color = x->color;
x->data = x->left->data;
x->color = x->left->color;
x->right = nw_node;
if(nw_node->left){ nw_node->left->parent = nw_node; }
if(nw_node->right){ nw_node->right->parent = nw_node; }
nw_node->parent = x;
if(x->left->left){ x->left = x->left->left; }
else { x->left = nullptr; }
if(x->left){ x->left->parent = x; }
}
void PreorderTraversal(node* temp) {
if(!temp){ return; }
cout << "--> " << temp->data << "<" << temp->color << ">";
PreorderTraversal(temp->left);
PreorderTraversal(temp->right);
}
void PostorderTraversal(node *temp) {
if(!temp){ return; }
PostorderTraversal(temp->left);
PostorderTraversal(temp->right);
cout << "--> " << temp->data << "<" << temp->color << ">";
}
};
void menu(){
cout << "\n__________________________________________";
cout << "\n\n --HEIGHT BALANCED BINARY SEARCH TREE--";
cout << "\n --(Red-Black-Tree)--";
cout << "\n__________________________________________";
cout << "\n\n1. Insert elements into the tree.";
cout << "\n2. Search for an element.";
cout << "\n3. PRE-ORDER Tree-Walk.";
cout << "\n4. POST-ORDER Tree-Walk.";
cout << "\n5. Remove an element from the tree.";
cout << "\n6. Exit.";
cout << "\n__________________________________________";
cout << "\nYour Choice -- ";
}
int main(){
RB_TREE demo;
int info, input;
menu();
cin >> info;
while(info != 6){
switch (info){
case 1: cout << "\nElement to be inserted -- ";
cin >> input; demo.InsertNode(input);
break;
case 2: cout << "\nElement to be searched -- ";
cin >> input;
if(demo.TreeSearch(input)) { cout << "Element found.\n"; }
else { cout << "Element not found.\n"; }
break;
case 3: cout << "Pre-Order Tree Walk ";
demo.PreorderTraversal(demo.GetRoot());
cout << endl;
break;
case 4: cout << "Post-Order Tree Walk ";
demo.PostorderTraversal(demo.GetRoot());
cout << endl;
break;
case 5: cout << "\nElement to be deleted? -- ";
cin >> input;
demo.Remove(input);
break;
default: cout << "Wrong Choice.\n";
}
cout << "\nAnything Else?";
cin >> info;
}
cout << "\nTerminating.... ";
return 0;
}
@abdullahqutb
Copy link

Not working, the recoloring has problems. Test this sequence, 35, 55, 75, 100, 80. all 75, 100, and 80 are red and two reds cant be one after the other.

@phuclv90
Copy link

phuclv90 commented Dec 3, 2019

Storing color as string is extremely inefficient. There are only 2 colors, so it should be stored as a bool

@pedrotorreao
Copy link

pedrotorreao commented Sep 22, 2020

Hey man, I hope you are doing fine!
On the code for the LeftRotate() method above, aren't we missing the recoloring of the x node? See below.

void LeftRotate(node* x) {
            node* nw_node = new node();
            if(x->right->left) { nw_node->right = x->right->left; }
            nw_node->left = x->left;
            nw_node->data = x->data;
            nw_node->color = x->color;
            x->data = x->right->data;
            x->color = x->right->color; **//this line here might be missing**
            x->left = nw_node;
            if(nw_node->left){ nw_node->left->parent = nw_node; }
            if(nw_node->right){ nw_node->right->parent = nw_node; }
            nw_node->parent = x;

            if(x->right->right){ x->right = x->right->right; }
            else { x->right = nullptr; }

            if(x->right){ x->right->parent = x; }
        }

Thanks for posting your code, man! Good job!

@pedrotorreao
Copy link

Also, on line 124 of the RemoveNode(...) method, since the idea here is to remove the left child of curr, shouldn't the recursive call be
RemoveNode(curr, curr->left, stuff);
instead of
RemoveNode(curr, curr->right, stuff); ?

Thanks again!

@osamaayub
Copy link

i am confused in one thing if user enters 1 insert value in the tree but if users enters 7 it should read the file .

@Hoek67
Copy link

Hoek67 commented May 17, 2021

Seems good... easy to make so the color is bool or uint8_t. Just interested in the order lowest to highest so fiddled the output function. Been looking for a fast BPlus Tree but this seemed just as good and has the right output.

Need fast ability to sort scene elements in a game engine which at the moment is a binary tree that's suffering due to being unbalanced for ~1000 inserts. I will pre-allocate all the nodes at the start and instead of allocating all the time just pull them from a pool. Also... due to this allocation pruning the tree is as simple as resetting the root each time.

   void InOrderTraversal(node* temp) 
    {
        if(!temp)
        {
            return; 
        }

        if (temp->left)
        {
            InOrderTraversal(temp->left);
             printf(">%d%c\n", temp->data,  (temp->color ? 'B' : 'R')) ;
        }
        else
        {
            printf(">%d%c\n", temp->data,  (temp->color ? 'B' : 'R')) ;
        }

        if (temp->right)
        {
            InOrderTraversal(temp->right);
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment