RBTree::tryDelete

This commit is contained in:
Timerix22 2024-05-01 19:41:35 +05:00
parent f2c6ad9b23
commit 0217edf080

View File

@ -152,9 +152,97 @@ class RBTree {
}
void fixupDeletion(Node* n){
// case 1
if(n->parent == nullptr)
return;
// case 2
Node* s = n->getSibling();
if(s->color == Color::Red){
n->parent->color = Color::Red;
s->color = Color::Black;
if (n == n->parent->left)
rotateLeft(n->parent);
else rotateRight(n->parent);
}
// case 3
if ((n->parent->color == Color::Black) &&
(s->color == Color::Black) &&
(s->left->color == Color::Black) &&
(s->right->color == Color::Black))
{
s->color = Color::Red;
fixupDeletion(n->parent);
return;
}
// case 4
else if ((n->parent->color == Color::Red) &&
(s->color == Color::Black) &&
(s->left->color == Color::Black) &&
(s->right->color == Color::Black))
{
s->color = Color::Red;
n->parent->color = Color::Black;
return;
}
// case 5
if(s->color == Color::Black) {
if ((n == n->parent->left) &&
(s->right->color == Color::Black) &&
(s->left->color == Color::Red))
{
s->color = Color::Red;
s->left->color = Color::Black;
rotateRight(s);
}
else if ((n == n->parent->right) &&
(s->left->color == Color::Black) &&
(s->right->color == Color::Red))
{
s->color = Color::Red;
s->right->color = Color::Black;
rotateLeft(s);
}
}
// case 6
s->color = n->parent->color;
n->parent->color = Color::Black;
if (n == n->parent->left) {
s->right->color = Color::Black;
rotateLeft(n->parent);
} else {
s->left->color = Color::Black;
rotateRight(n->parent);
}
}
void transplantNode(Node* old, Node* neww){
neww->parent = old->parent;
if(old->parent == nullptr)
root = neww;
else if(old->parent->left == old)
old->parent->left = neww;
else old->parent->right = neww;
}
// n should be not null
Node* getMinimalChild(Node* n){
while(n->left != nullptr)
n = n->left;
return n;
}
// n should be not null
Node* getMaximalChild(Node* n){
while(n->right != nullptr)
n = n->right;
return n;
}
public:
RBTree() {}
@ -163,6 +251,8 @@ public:
delete root;
}
bool tryAdd(TKey key, TVal& value, TVal*& result){
if(root == nullptr){
root = new Node(key, value, Color::Black, nullptr);
@ -171,18 +261,18 @@ public:
Node* parent = findParentForKey(key);
// ptr to parent->right or parent->left
Node** leftOrRightPtr;
Node** nodePtrPtr;
if(key < parent->key)
leftOrRightPtr = &parent->left;
else leftOrRightPtr = &parent->right;
nodePtrPtr = &parent->left;
else nodePtrPtr = &parent->right;
// if a child node already exists at this place, returns false
if(*leftOrRightPtr != nullptr)
if(*nodePtrPtr != nullptr)
return false;
// places newNode to left or right of the parent
Node* newNode = new Node(key, value, Color::Red, parent);
*leftOrRightPtr = newNode;
*nodePtrPtr = newNode;
// auto-balancing
fixupInsertion(newNode);
return true;
@ -194,17 +284,17 @@ public:
Node* parent = findParentForKey(key);
// ptr to parent->right or parent->left
Node** leftOrRightPtr;
Node** nodePtrPtr;
if(key < parent->key)
leftOrRightPtr = &parent->left;
else leftOrRightPtr = &parent->right;
nodePtrPtr = &parent->left;
else nodePtrPtr = &parent->right;
// if a child node with the given key doesn't exist, returns false
if(*leftOrRightPtr == nullptr)
if(*nodePtrPtr == nullptr)
return false;
// replaces the value of left or right child of the parent
(*leftOrRightPtr)->value = value;
(*nodePtrPtr)->value = value;
return true;
}
@ -216,20 +306,20 @@ public:
Node* parent = findParentForKey(key);
// ptr to parent->right or parent->left
Node** leftOrRightPtr;
Node** nodePtrPtr;
if(key < parent->key)
leftOrRightPtr = &parent->left;
else leftOrRightPtr = &parent->right;
nodePtrPtr = &parent->left;
else nodePtrPtr = &parent->right;
// if a child node already exists at this place, sets it's value
if(*leftOrRightPtr != nullptr){
(*leftOrRightPtr)->value = value;
if(*nodePtrPtr != nullptr){
(*nodePtrPtr)->value = value;
return;
}
// places newNode to left or right of the parent
Node* newNode = new Node(key, value, Color::Red, parent);
*leftOrRightPtr = newNode;
*nodePtrPtr = newNode;
// auto-balancing
fixupInsertion(newNode);
}
@ -249,6 +339,39 @@ public:
}
bool tryDelete(TKey key){
Node* parent = findParentForKey(key);
Node* n;
if(key < parent->key)
n = parent->left;
else n = parent->right;
if(n == nullptr) // key not found
return false;
if(n->left == nullptr){
transplantNode(n, n->right);
if(n->color == Color::Black)
fixupDeletion(n->right);
}
else if(n->right == nullptr){
transplantNode(n, n->left);
if(n->color == Color::Black)
fixupDeletion(n->left);
}
else {
Node* minNode = getMinimalChild(n->right);
if(minNode != n->right){
transplantNode(minNode, minNode->right);
minNode->right = n->right;
n->right->parent = minNode;
}
// else minNode->right->parent = minNode; // wtf???
transplantNode(n, minNode);
minNode->left = n->left;
n->left->parent = minNode;
if(minNode->color == Color::Black)
fixupDeletion(minNode->right);
}
delete n;
}
};