【发布时间】:2021-06-27 08:15:28
【问题描述】:
我正在尝试制作 RB 树的 C++ 实现。但是当我尝试删除一个元素时 - 我发现树的一些叶子具有不同的黑色高度值。在调用 remove 函数之前一切正常 - 树插入后的插入和重新平衡正常工作。但是在一次调用 remove 函数之后,它就不再平衡了。
一般删除:
void RbTree::remove(int data) {
Node* cur = root;
while (cur != nil && cur->data != data) { // Searching for node with expected key
if (cur->data < data)
cur = cur->RIGHT;
else
cur = cur->LEFT;
if (cur == nil)
return;
}
removeNode(cur); // Recurrent BST node removing
RbTree::Node* RbTree::removeNode(Node*& cur) {
if (cur->RIGHT == nil && cur->LEFT == nil) { // No children
Node* dad = cur->ancestor;
if (cur == root) { // If current node is root
cur = root = nil;
} else { // Dad now points to nil
if (cur->color == BLACK)
fixRemoving(cur);
dad->RIGHT == cur ? dad->RIGHT = nil : dad->LEFT = nil;
}
} else if (!(cur->RIGHT != nil && cur->LEFT != nil)) { // If there's only one children for current node
Node* dad = cur->ancestor;
Node* son;
cur->RIGHT != nil ? son = cur->RIGHT : son = cur->LEFT; // Searching for son
dad->RIGHT == cur ? dad->RIGHT = son : dad->LEFT = son; // Dad now points to son
son->ancestor = dad;
son->color = BLACK; // Changing son's color
if (cur->color == BLACK) {
fixRemoving(son);
}
} else { // If left and right child exist
Node* found = findMin(cur->RIGHT); // Finding the least element in right subtree
cur->data = found->data; // Copying data
removeNode(found); // Recurrently remove found node
}
return cur;
修复删除功能:
void RbTree::fixRemoving(Node*& node) {
Node* dad = node->ancestor;
Node* bro;
if (node == dad->LEFT) {
bro = dad->RIGHT;
if (bro->color == RED) {
bro->color = BLACK;
dad->color = RED;
leftRotate(dad);
bro = dad->RIGHT;
}
Node* leftNephew = bro->LEFT;
Node* rightNephew = bro->RIGHT;
if (leftNephew->color == BLACK && rightNephew->color == BLACK) { // 1) If both of bro's children are black
bro->color = RED;
dad->color = BLACK;
fixRemoving(dad);
return;
} else if (leftNephew->color == RED) { // 2) Else if only left is red - we need to make those steps and go to 3)
leftNephew->color = BLACK;
bro->color = RED;
rightRotate(bro);
}
rightNephew->color = BLACK; // 3) Now left nephew is black and right is red
bro->color = dad->color;
dad->color = BLACK;
leftRotate(dad);
} else { // Same things there
bro = dad->LEFT;
if (bro->color == RED) {
bro->color = BLACK;
dad->color = RED;
rightRotate(dad);
bro = dad->LEFT;
}
Node* leftNephew = bro->LEFT;
Node* rightNephew = bro->RIGHT;
if (leftNephew->color == BLACK && rightNephew->color == BLACK) {
bro->color = RED;
dad->color = BLACK;
fixRemoving(dad);
return;
} else if (leftNephew->color == RED) {
leftNephew->color = BLACK;
bro->color = RED;
rightRotate(bro);
}
rightNephew->color = BLACK;
bro->color = dad->color;
dad->color = BLACK;
rightRotate(dad);
}
我想我可能有以下问题:
- 使用右节点参数调用 fixRemoving 函数
- fixRemoving 方法的主体
我正在使用的算法:
- 找到一个我们想要删除的节点,就像我们在普通 BST 中所做的那样。
- 如果它没有子节点 - 只需删除它,如果它只有 1 个子节点 - 我们放置这个子节点而不是可移动节点,将其涂成黑色。
- 如果它有两个孩子 - 我们会在右子树中找到最少的元素并反复删除它。
- 如果节点的原始颜色是黑色 - 那么我们需要修复一棵树。
修复算法在代码中描述 - 我希望不需要额外的信息。
请帮忙!
【问题讨论】:
标签: c++ algorithm tree red-black-tree