红黑树是特殊的搜索树,除了要满足搜索树外,还得满足color的要求。原则上说树的所有操作只有两种:插入和删除。
基本知识左旋、右旋、最小后继和节点替换不在重复。只针对插入和删除,说其内部原理。
插入:
插入一个元素时,由于红黑树根本也是一棵搜索树,所以可以先用搜索树的方式插入一个元素。由于在末尾添加的元素,如果置黑,可能导致其他树的黑路径长度少一。置红的话就不存在这个问题,只会存在两个红节点相邻的问题。解决这个问题,比较简单:两个红节点相邻,则下方的红节点树一定排列正确,只需要考虑上方的节点,通过左旋或者右旋将红节点不停往上传递即可。
删除:
删除任意一个节点,和搜索树一样,如果该节点有单子树,只需要将单树替换到该节点(注意颜色不改变)即可,否则,其他的删除,从本质上来说都是删除叶子结点。
如果删除的节点是黑色,会导致该树上黑色节点数目少一,为保持平衡,则将替换的nil置“双黑”,然后根据算法导论书上的描述处理即可。这里只注意nil是黑节点(虽然我们是用null替代的),故为了处理方便,我在fix上额外添加了一个参数parent。
具体实现请查看代码,细节问题可以讨论,如果哪里写错了,欢迎指正!
#define RED 1
#define BLACK 0
typedef struct TreeNode
{
TreeNode* left;
TreeNode* right;
TreeNode* parent;
int value;
};
typedef struct TreeNodeColor : public TreeNode
{
int color;
};
typedef struct Tree
{
TreeNode* root;
};
//一定存在右子节点
void Left_Rotate(Tree *root, TreeNode *node)
{
if (!node || !node->right)
{
return;
}
TreeNode* right = node->right;
node->right = right->left;
if (right->left != NULL)
{
right->left->parent = node;
right->left = node;
}
TreeNode* parent = node->parent;
node->parent = right;
if (parent != NULL)
{
if (parent->left == node)
{
parent->left = right;
}
else
{
parent->right = right;
}
}
else
{
root->root = right;
}
right->parent = parent;
}
//一定有父节点
void Right_Rotate(Tree *root, TreeNode *node)
{
if (!node || !node->parent)
{
return;
}
TreeNode* parent = node->parent;
parent->left = node->right;
node->right = parent;
TreeNode* temp = parent->parent;
if (temp != NULL)
{
if (temp->left == parent)
{
temp->left = node;
}
else
{
temp->right = node;
}
}
else
{
root->root = node;
}
if (parent->left != NULL)
{
parent->left->parent = parent;
}
}
void Rotate(Tree* root, TreeNode* node, int isLeft)
{
if (isLeft)
{
Left_Rotate(root, node);
}
else
{
Right_Rotate(root, node);
}
}
//node的父树的两个子树肯定已经排好了,处理父树就好了
//只需要处理红节点,则node对应的肯定是红节点
//这个过程处理结束后,只剩下根节点,最后将其重置为红色即可
void insertFixupWithoutRoot(Tree* root, TreeNodeColor* node)
{
if (node == NULL)
{
return;
}
TreeNodeColor* parent = (TreeNodeColor*)node->parent;
//必要条件:node有父 node的父为红节点
//node的父树一定也有父,如果没有父说明处理到根节点,当返回了
if (parent && parent->parent&& parent->color == RED)
{
TreeNodeColor* other;
int flag_parent = 1, flat_cur = 1;
//找到p->p的另一个子节点
if (parent->parent->left == parent)
{
other = (TreeNodeColor*)parent->right;
}
else
{
other = (TreeNodeColor*)parent->left;
flag_parent = 0;
}
if (parent->right == node)
{
flat_cur = 0;
}
if (!other && other->color == RED)//会产生红节点,并会影响到对其父树
{
other->color = BLACK;
node->color = BLACK;
parent->color = RED;
insertFixupWithoutRoot(root, parent);
}
else//会产生红节点,通过旋转,被内部消化
{
if (flag_parent != flat_cur)
{
node = parent;
if (flat_cur)
{
Left_Rotate(root, parent);
}
else
{
Right_Rotate(root, parent);
}
}
((TreeNodeColor*)node->parent)->color = BLACK;
//在旋转过后这个红节点不会有影响
((TreeNodeColor*)node->parent->parent)->color = RED;
if (flag_parent)
{
Right_Rotate(root, node->parent->parent);
}
else
{
Left_Rotate(root, node->parent->parent);
}
}
}
}
//添加黑节点后稳固树
void insert_fixup(Tree* root, TreeNodeColor* node)
{
//先处理完所有非根节点
insertFixupWithoutRoot(root, node);
//重置根节点颜色
((TreeNodeColor*)root->root)->color = BLACK;
}
//删除黑节点后平衡整个树
void delete_fixup(Tree* root, TreeNodeColor* node, TreeNodeColor* parent)
{
if (parent == NULL)
{
return;
}
TreeNodeColor* other;
if (parent->left == node)
{
other = (TreeNodeColor*)parent->right;
}
else
{
other = (TreeNodeColor*)parent->left;
}
TreeNodeColor* other_left = (TreeNodeColor*)other->left;
TreeNodeColor* other_right = (TreeNodeColor*)other->right;
if (other->color == RED) // case 1
{
Rotate(root, parent, node == parent->left);
delete_fixup(root, node, parent);
}
else if ((!other_left || other_left->color == BLACK) && (!other_right || other_right->color == BLACK)) // case 2
{
int color = parent->color;
parent->color = BLACK;
other->color = RED;
if (color == BLACK)
{
delete_fixup(root, parent, (TreeNodeColor*)parent->parent);
}
}
else if (other_left && other_left->color == RED && (!other_right || other_right->color == BLACK)) //case 3
{
other_left->color = BLACK;
other->color = RED;
Rotate(root, parent, false);
delete_fixup(root, node, parent);
}
else if (other_right && other_right->color == RED) // case 4
{
int color = parent->color;
other_right->color = BLACK;
parent->color = BLACK;
other->color = color;
Rotate(root, parent, true);
}
}
void insert(Tree *root, TreeNodeColor* node)
{
TreeNode *parent = node->parent, *cur = root->root;
while (cur != NULL)
{
parent = cur;
if (cur->value < node->value)
{
cur = cur->right;
}
else
{
cur = cur->left;
}
}
if (parent == NULL)
{
root->root = node;
}
else
{
if (parent->value < node->value)
{
parent->right = node;
}
else
{
parent->left = node;
}
}
node->parent = parent;
node->color = RED;
insert_fixup(root, node);
}
//节点替换
void transplant(Tree* root, TreeNode* node, TreeNode* replace_node)
{
if (node && node->parent)
{
if (node->parent->left == node)
{
node->parent->left = replace_node;
}
else
{
node->parent->right = replace_node;
}
}
else
{
root->root = replace_node;
}
if (replace_node)
{
replace_node->parent = node->parent;
}
}
TreeNode* minmum(TreeNode *node)
{
TreeNode *result = node;
while (result->left)
{
result = result->left;
}
return result;
}
//删除黑节点时,会导致一部分树出现失衡
//出现失衡后,需要将多余的黑树上报给根节点
void del(Tree *root, TreeNodeColor* node)
{
int color;
if (!node->left || !node->right)//单子树肯定不会存在右子树为黑的情况
{
TreeNodeColor* temp = (TreeNodeColor*)(node->left ? node->left : node->right);
transplant(root, node, temp);
if (temp)
{
temp->color = node->color;
}
else if(node->color == BLACK)
{
delete_fixup(root, NULL, (TreeNodeColor*)node->parent);
}
}
else
{
TreeNodeColor* min = (TreeNodeColor*)minmum(node->right);
node->value = min->value;
del(root, min);
}
((TreeNodeColor*)root->root)->color = BLACK;
}