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