Skip to content

Instantly share code, notes, and snippets.

@SubCoder1
Created August 22, 2018 17:26
Show Gist options
  • Select an option

  • Save SubCoder1/70c2cedc44353ffc539c7567b1051028 to your computer and use it in GitHub Desktop.

Select an option

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

Copy link
Copy Markdown

The Insertion Algorithm

Nodes are always inserted as RED nodes at their designated BST position. If the parent node is black, no invariants are broken. If the parent node is red, it introduces a "Red-Red violation" that is fixed using three distinct cases depending on the color of the parent's sibling (the uncle node)

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