mirea-projects/Second term/Algorithms/2/5.cpp

320 lines
9.8 KiB
C++
Raw Normal View History

2024-09-23 23:22:33 +00:00
#include <ctime>
#include <iostream>
#define RED true
#define BLACK false
using namespace std;
struct Node {
int key;
Node *left;
Node *right;
Node *parent;
bool color;
Node(int value) : key(value), left(nullptr), right(nullptr), color(RED) {}
};
bool getColor(Node *node) {
if (node == nullptr) return BLACK;
return node->color;
}
void setColor(Node *node, bool color) {
if (node == nullptr) return;
node->color = color;
}
void rightRotate(Node *&root, Node *&node) {
Node *leftChild = node->left;
node->left = leftChild->right;
if(node->left != nullptr) node->left->parent = node;
leftChild->parent = node->parent;
if(node->parent == nullptr) root = leftChild;
else if(node == node->parent->left) node->parent->left = leftChild;
else node->parent->right = leftChild;
leftChild->right = node;
node->parent = leftChild;
}
void leftRotate(Node *&root, Node *&node) {
Node *rightChild = node->right;
node->right = rightChild->left;
if(node->right != nullptr) node->right->parent = node;
rightChild->parent = node->parent;
if(node->parent == nullptr) root = rightChild;
else if(node == node->parent->left) node->parent->left = rightChild;
else node->parent->right = rightChild;
rightChild->left = node;
node->parent = rightChild;
}
void fixRulesAfterInsertion(Node *&root, Node*& node) {
Node* parent = nullptr;
Node* grandParent = nullptr;
while (node != root && getColor(node) == RED && getColor(node->parent) == RED) {
parent = node->parent;
grandParent = parent->parent;
if(parent == grandParent->left) {
Node* uncle = grandParent->right;
if(getColor(uncle) == RED) {
setColor(uncle, BLACK);
setColor(parent, BLACK);
setColor(grandParent, RED);
node = grandParent;
}
else {
if(node == parent->right) {
leftRotate(root, parent);
node = parent;
parent = node->parent;
}
rightRotate(root, grandParent);
const bool color = grandParent->color;
grandParent->color = parent->color;
parent->color = color;
node = parent;
}
}
else {
Node* uncle = grandParent->left;
if(getColor(uncle) == RED) {
setColor(uncle, BLACK);
setColor(parent, BLACK);
setColor(grandParent, RED);
node = grandParent;
}
else {
if(node == parent->left) {
rightRotate(root, parent);
node = parent;
parent = node->parent;
}
leftRotate(root, grandParent);
const bool color = grandParent->color;
grandParent->color = parent->color;
parent->color = color;
node = parent;
}
}
}
setColor(root, BLACK);
}
void insertNode(Node *&root, Node *&node) {
if (root == nullptr) {
root = node;
return;
}
if (node->key < root->key) {
insertNode(root->left, node);
root->left->parent = root;
}
else if (node->key >= root->key) {
insertNode(root->right, node);
root->right->parent = root;
}
}
void insertNodeValue(Node *&root, const int key) {
Node *node = new Node(key);
insertNode(root, node);
fixRulesAfterInsertion(root, node);
}
Node *search(Node *&node, int key) {
if (node == nullptr) return nullptr;
if (node->key == key) return node;
return search((node->key > key) ? node->left : node->right, key);
}
Node *getMin(Node *&node) {
if (node == nullptr) return nullptr;
if (node->left == nullptr) return node;
return getMin(node->left);
}
Node *getMax(Node *&node) {
if (node == nullptr) return nullptr;
if (node->right == nullptr) return node;
return getMax(node->right);
}
int getChildrenCount(Node *&node) {
int count = 0;
if (node->left != nullptr) count++;
if (node->right != nullptr) count++;
return count;
}
Node *getChildOrMock(Node*& node) {
return node->left != nullptr ? node->left : node->right;
}
void transplantNode(Node *&root, Node *&toNode, Node *&fromNode) {
if (toNode == root) root = toNode;
else if (toNode == toNode->parent->left) toNode->parent->left = fromNode;
else toNode->parent->right = fromNode;
fromNode->parent = toNode->parent;
}
void fixRulesAfterRemoval(Node *&root, Node *&node) {
if (node == nullptr) return;
if (node == root) {
root = nullptr;
return;
}
if (getColor(node) == RED || getColor(node->left) == RED || getColor(node->right) == RED) {
Node *child = node->left != nullptr ? node->left : node->right;
if (node == node->parent->left) {
node->parent->left = child;
if (child != nullptr) child->parent = node->parent;
setColor(child, BLACK);
delete (node);
} else {
node->parent->right = child;
if (child != nullptr) child->parent = node->parent;
setColor(child, BLACK);
delete (node);
}
} else {
Node *sibling = nullptr;
Node *parent = nullptr;
Node *ptr = node;
setColor(ptr, BLACK);
while (ptr != root && getColor(ptr) == BLACK) {
parent = ptr->parent;
if (ptr == parent->left) {
sibling = parent->right;
if (getColor(sibling) == RED) {
setColor(sibling, BLACK);
setColor(parent, RED);
leftRotate(root, parent);
} else {
if (getColor(sibling->left) == BLACK && getColor(sibling->right) == BLACK) {
setColor(sibling, RED);
if(getColor(parent) == RED) setColor(parent, BLACK);
else setColor(parent, BLACK);
ptr = parent;
} else {
if (getColor(sibling->right) == BLACK) {
setColor(sibling->left, BLACK);
setColor(sibling, RED);
rightRotate(root, sibling);
sibling = parent->right;
}
setColor(sibling, parent->color);
setColor(parent, BLACK);
setColor(sibling->right, BLACK);
leftRotate(root, parent);
break;
}
}
} else {
sibling = parent->left;
if (getColor(sibling) == RED) {
setColor(sibling, BLACK);
setColor(parent, RED);
rightRotate(root, parent);
} else {
if (getColor(sibling->left) == BLACK && getColor(sibling->right) == BLACK) {
setColor(sibling, RED);
if (getColor(parent) == RED) setColor(parent, BLACK);
else setColor(parent, BLACK);
ptr = parent;
} else {
if (getColor(sibling->left) == BLACK) {
setColor(sibling->right, BLACK);
setColor(sibling, RED);
leftRotate(root, sibling);
sibling = parent->left;
}
setColor(sibling, parent->color);
setColor(parent, BLACK);
setColor(sibling->left, BLACK);
rightRotate(root, parent);
break;
}
}
}
}
if (node == node->parent->left) node->parent->left = nullptr;
else node->parent->right = nullptr;
delete(node);
setColor(root, BLACK);
}
}
Node *deleteNode(Node *&node, int key) {
if (node == nullptr) return nullptr;
if (node->key > key) return deleteNode(node->left, key);
if (node->key < key) return deleteNode(node->right, key);
if (node->left == nullptr || node->right == nullptr) return node;
Node *minRight = getMin(node->right);
node->key = minRight->key;
return deleteNode(node->right, minRight->key);
}
void deleteNodeValue(Node *&root, const int key) {
Node* node = deleteNode(root, key);
fixRulesAfterRemoval(root, node);
}
void printTree(Node *node) {
if (node == nullptr) return;
printTree(node->left);
cout << node->key << " (" << ((node->color == RED) ? "RED" : "BLACK") << ")"<< endl;
printTree(node->right);
}
Node *generateRandomTree(int countOfNodes) {
Node *root = nullptr;
for (; countOfNodes > 0; countOfNodes--) insertNodeValue(root, rand() % 100);
return root;
}
int blackHeight(Node* node) {
if (node == nullptr) return 1;
int leftHeight = blackHeight(node->left);
int rightHeight = blackHeight(node->right);
if (leftHeight != rightHeight) return 0;
if (leftHeight == 0 || rightHeight == 0) return 0;
if (getColor(node) == BLACK) leftHeight++;
return leftHeight;
}
void checkRedBlackTreeProperties(Node* root) {
cout << "Checking for rules: ";
if (blackHeight(root) != 0)
cout << "Correct" << endl;
else
cout << "Incorrect" << endl;
}
int main() {
srand(time(0));
Node *root = generateRandomTree(10);
printTree(root);
checkRedBlackTreeProperties(root);
cout << "rm " << root->key << endl;
deleteNodeValue(root, root->key);
printTree(root);
checkRedBlackTreeProperties(root);
return 0;
}