兄弟至少一个红孩子
LL
- 变色:首先r结点的颜色变为s结点的颜色,然后s结点的颜色变为p结点的颜色,最后p结点的颜色变为黑色
- 对p结点进行右旋
- 双黑变单黑
RR
与LL型相同
- 变色:首先r结点的颜色变为s结点的颜色,然后s结点的颜色变为p结点的颜色,最后p结点的颜色变为黑色
- 对p结点进行左旋
- 双黑变单黑
LR、RL
LR、RL二者差不多
LR:
- 首先r结点的颜色变为p结点的颜色,然后p结点的颜色变为黑色
- LR型:对p结点的左孩子s结点(5)左旋
- 右旋结点p
- 双黑变单黑
代码实现
在STL中,我们常分为 RL+RR、LR+LL两组,因为RR和LR后面的步骤都是一样的,RL和RR后面的步骤都是一样的
我们以RL+RR为例:
bool isRL = false;
// 兄弟结点右孩子是黑的,所以左孩子一定是红的
if(getColor(sibling->right) == Color::BLACK)
{
isRL = true;
// RL变色规则
if(isRL)
{
setColor(sibling->left, getColor(node->parent));
setColor(node->parent, Color::BLACK);
}
// 兄弟结点右旋
rightRotate(sibling);
// 旋转后更正兄弟结点指向
sibling = node->parent->right;
}
// RR类型
// RR变色规则,跟RL类型不同
if(!isRL)
{
setColor(sibling->right, getColor(sibling));
setColor(sibling, getColor(node->parent));
setColor(node->parent, Color::BLACK);
}
// 左旋结点
leftRotate(node->parent);
node = root;
在上述代码中,我们使用一个布尔变量isRL
判断是RR类型还是RL类型,这是因为二者的变色规则不一样
LL+LR:
bool isLR = false;
// 结点左孩子是黑的,所以右孩子一定是红的
if(getColor(sibling->left) == Color::BLACK)
{
isLR = true;
// LR类型变色规则
if(isLR)
{
setColor(sibling->right, getColor(node->parent));
setColor(node->parent, Color::BLACK);
}
// 兄弟结点左旋
leftRotate(sibling);
// 旋转后更正兄弟结点
sibling = node->parent->left;
}
// LL类型
if(!isLR)
{
setColor(sibling->left, getColor(sibling));
setColor(sibling, getColor(node->parent));
setColor(node->parent, Color::BLACK);
}
// 右旋结点
rightRotate(node->parent);
node = root;
兄弟孩子都是黑色
代码实现
// 兄弟变红
setColor(sibling, Color::RED);
// 双黑上移
node = node ->parent;
if(node->color == Color::RED)
{
// 上移是红,变单黑
node->color = Color::BLACK;
// 结束循环
node = root;
}
兄弟是红色
兄父变色,朝双黑方向旋转,保持双黑继续调整
如下图所示,我们要删除一个15,实际上是找15的右子树上,最小值(17),替换15,实际上,就是删除17
此时原来的17就变成了双黑结点,此时兄弟结点是红色(34)
则兄父变色:23变成红色,34变成黑色