From 0217edf080c7f21eabf3ea051fe68b9a281d380a Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Wed, 1 May 2024 19:41:35 +0500 Subject: [PATCH] RBTree::tryDelete --- src/RBTree.hpp | 159 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 141 insertions(+), 18 deletions(-) diff --git a/src/RBTree.hpp b/src/RBTree.hpp index 4569d71..b7f2579 100644 --- a/src/RBTree.hpp +++ b/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; + } };