RBTree::tryDelete
This commit is contained in:
parent
f2c6ad9b23
commit
0217edf080
155
src/RBTree.hpp
155
src/RBTree.hpp
@ -152,9 +152,97 @@ class RBTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user