diff --git a/map/src/map.hpp b/map/src/map.hpp index 1aaa76a..a6794b6 100644 --- a/map/src/map.hpp +++ b/map/src/map.hpp @@ -263,6 +263,82 @@ class map { path_of_successor = node; } } + void DeleteFixUp(RedBlackTreeNodeType *&tree_root) { + assert(this->left == nullptr && this->right == nullptr); + assert(this->color == RedBlackTreeColorType::BLACK); + RedBlackTreeNodeType *sibling = GetSibling(); + assert(sibling != nullptr); + if (sibling->color == RedBlackTreeColorType::RED) { + // Case 1 + parent->color = RedBlackTreeColorType::RED; + sibling->color = RedBlackTreeColorType::BLACK; + if (this == parent->left) { + parent->RotateLeft(tree_root); + } else { + parent->RotateRight(tree_root); + } + this->DeleteFixUp(tree_root); + return; + } + RedBlackTreeNodeType *close_nephew = nullptr; + RedBlackTreeNodeType *distant_nephew = nullptr; + if (this == parent->left) { + close_nephew = sibling->left; + distant_nephew = sibling->right; + } else { + close_nephew = sibling->right; + distant_nephew = sibling->left; + } + if (sibling->color == RedBlackTreeColorType::BLACK && this->parent->color == RedBlackTreeColorType::RED && + (close_nephew == nullptr || close_nephew != nullptr && close_nephew->color == RedBlackTreeColorType::BLACK) && + (distant_nephew == nullptr || + distant_nephew != nullptr && distant_nephew->color == RedBlackTreeColorType::BLACK)) { + // Case 2 + assert(close_nephew == nullptr); + assert(distant_nephew == nullptr); + sibling->color = RedBlackTreeColorType::RED; + this->parent->color = RedBlackTreeColorType::BLACK; + return; + } + if (sibling->color == RedBlackTreeColorType::BLACK && this->parent->color == RedBlackTreeColorType::BLACK && + (close_nephew == nullptr || close_nephew != nullptr && close_nephew->color == RedBlackTreeColorType::BLACK) && + (distant_nephew == nullptr || + distant_nephew != nullptr && distant_nephew->color == RedBlackTreeColorType::BLACK)) { + // Case 3 + assert(close_nephew == nullptr); + assert(distant_nephew == nullptr); + sibling->color = RedBlackTreeColorType::RED; + this->parent->DeleteFixUp(tree_root); + return; + } + if (close_nephew != nullptr && close_nephew->color == RedBlackTreeColorType::RED) { + // Case 4 + if (this == parent->left) { + sibling->color = RedBlackTreeColorType::RED; + close_nephew->color = RedBlackTreeColorType::BLACK; + sibling->RotateRight(tree_root); + } else { + sibling->color = RedBlackTreeColorType::RED; + close_nephew->color = RedBlackTreeColorType::BLACK; + sibling->RotateLeft(tree_root); + } + this->DeleteFixUp(tree_root); + return; + } + assert(distant_nephew != nullptr && distant_nephew->color == RedBlackTreeColorType::RED); + // Then it must be Case 5 + if (this == parent->left) { + sibling->color = parent->color; + parent->color = RedBlackTreeColorType::BLACK; + distant_nephew->color = RedBlackTreeColorType::BLACK; + parent->RotateLeft(tree_root); + } else { + sibling->color = parent->color; + parent->color = RedBlackTreeColorType::BLACK; + distant_nephew->color = RedBlackTreeColorType::BLACK; + parent->RotateRight(tree_root); + } + } static void DeleteNode(RedBlackTreeNodeType *pos, RedBlackTreeNodeType *&tree_root) { if (pos->parent == nullptr && pos->left == nullptr && pos->right == nullptr) { // Case 0: The only node in the tree. @@ -280,11 +356,12 @@ class map { } if (pos->left == nullptr && pos->right == nullptr) { // Case 2 - if (pos->color == RedBlackTreeColorType::RED) { - pos->GetSelfPath(tree_root) = nullptr; - delete pos; - return; + if (pos->color == RedBlackTreeColorType::BLACK) { + pos->DeleteFixUp(tree_root); } + pos->GetSelfPath(tree_root) = nullptr; + delete pos; + return; } // Case 3 RedBlackTreeNodeType *replacement = (pos->left != nullptr ? pos->left : pos->right); @@ -295,16 +372,16 @@ class map { replacement->color = RedBlackTreeColorType::BLACK; delete pos; } + static void CopyFrom(RedBlackTreeNodeType *&target, const RedBlackTreeNodeType *source) { + if (source == nullptr) return; + target = new RedBlackTreeNodeType(source->val, nullptr, nullptr, nullptr, source->color); + CopyFrom(target->left, source->left); + CopyFrom(target->right, source->right); + target->SetChildrensParent(); + } }; size_t node_count; RedBlackTreeNodeType *tree_root; - void CopyFrom(RedBlackTreeNodeType *&target, const RedBlackTreeNodeType *source) { - if (source == nullptr) return; - target = new RedBlackTreeNodeType(source->val, nullptr, nullptr, nullptr, source->color); - CopyFrom(target->left, source->left); - CopyFrom(target->right, source->right); - target->SetChildrensParent(); - } public: /** @@ -497,7 +574,7 @@ class map { map() : node_count(0), tree_root(nullptr) {} map(const map &other) { node_count = other.node_count; - CopyFrom(tree_root, other.tree_root); + RedBlackTreeNodeType::CopyFrom(tree_root, other.tree_root); } map(map &&other) { node_count = other.node_count; @@ -513,7 +590,7 @@ class map { if (tree_root) tree_root->ReleaseAll(); delete tree_root; node_count = other.node_count; - CopyFrom(tree_root, other.tree_root); + RedBlackTreeNodeType::CopyFrom(tree_root, other.tree_root); return *this; } map &operator=(map &&other) {