RBTree::tryDelete

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

View File

@ -150,11 +150,99 @@ class RBTree {
rotateRight(g); rotateRight(g);
else rotateLeft(g); else rotateLeft(g);
} }
void fixupDeletion(Node* n){ 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: public:
RBTree() {} RBTree() {}
@ -163,6 +251,8 @@ public:
delete root; delete root;
} }
bool tryAdd(TKey key, TVal& value, TVal*& result){ bool tryAdd(TKey key, TVal& value, TVal*& result){
if(root == nullptr){ if(root == nullptr){
root = new Node(key, value, Color::Black, nullptr); root = new Node(key, value, Color::Black, nullptr);
@ -171,18 +261,18 @@ public:
Node* parent = findParentForKey(key); Node* parent = findParentForKey(key);
// ptr to parent->right or parent->left // ptr to parent->right or parent->left
Node** leftOrRightPtr; Node** nodePtrPtr;
if(key < parent->key) if(key < parent->key)
leftOrRightPtr = &parent->left; nodePtrPtr = &parent->left;
else leftOrRightPtr = &parent->right; else nodePtrPtr = &parent->right;
// if a child node already exists at this place, returns false // if a child node already exists at this place, returns false
if(*leftOrRightPtr != nullptr) if(*nodePtrPtr != nullptr)
return false; return false;
// places newNode to left or right of the parent // places newNode to left or right of the parent
Node* newNode = new Node(key, value, Color::Red, parent); Node* newNode = new Node(key, value, Color::Red, parent);
*leftOrRightPtr = newNode; *nodePtrPtr = newNode;
// auto-balancing // auto-balancing
fixupInsertion(newNode); fixupInsertion(newNode);
return true; return true;
@ -194,17 +284,17 @@ public:
Node* parent = findParentForKey(key); Node* parent = findParentForKey(key);
// ptr to parent->right or parent->left // ptr to parent->right or parent->left
Node** leftOrRightPtr; Node** nodePtrPtr;
if(key < parent->key) if(key < parent->key)
leftOrRightPtr = &parent->left; nodePtrPtr = &parent->left;
else leftOrRightPtr = &parent->right; else nodePtrPtr = &parent->right;
// if a child node with the given key doesn't exist, returns false // if a child node with the given key doesn't exist, returns false
if(*leftOrRightPtr == nullptr) if(*nodePtrPtr == nullptr)
return false; return false;
// replaces the value of left or right child of the parent // replaces the value of left or right child of the parent
(*leftOrRightPtr)->value = value; (*nodePtrPtr)->value = value;
return true; return true;
} }
@ -216,20 +306,20 @@ public:
Node* parent = findParentForKey(key); Node* parent = findParentForKey(key);
// ptr to parent->right or parent->left // ptr to parent->right or parent->left
Node** leftOrRightPtr; Node** nodePtrPtr;
if(key < parent->key) if(key < parent->key)
leftOrRightPtr = &parent->left; nodePtrPtr = &parent->left;
else leftOrRightPtr = &parent->right; else nodePtrPtr = &parent->right;
// if a child node already exists at this place, sets it's value // if a child node already exists at this place, sets it's value
if(*leftOrRightPtr != nullptr){ if(*nodePtrPtr != nullptr){
(*leftOrRightPtr)->value = value; (*nodePtrPtr)->value = value;
return; return;
} }
// places newNode to left or right of the parent // places newNode to left or right of the parent
Node* newNode = new Node(key, value, Color::Red, parent); Node* newNode = new Node(key, value, Color::Red, parent);
*leftOrRightPtr = newNode; *nodePtrPtr = newNode;
// auto-balancing // auto-balancing
fixupInsertion(newNode); fixupInsertion(newNode);
} }
@ -249,6 +339,39 @@ public:
} }
bool tryDelete(TKey key){ 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;
}
}; };