RBTree::tryDelete
This commit is contained in:
parent
f2c6ad9b23
commit
0217edf080
159
src/RBTree.hpp
159
src/RBTree.hpp
@ -150,11 +150,99 @@ class RBTree {
|
||||
rotateRight(g);
|
||||
else rotateLeft(g);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user