-
-
Save SubCoder1/70c2cedc44353ffc539c7567b1051028 to your computer and use it in GitHub Desktop.
#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; | |
} |
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!
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 .
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);
}
}
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.
Thanks for posting your code, man! Good job!