基调
只有当插入节点的父节点是红色,才需要调整
一、情况
情况1
状态:当前节点的叔节点也是红色
解决方案:
1. 将父节点设为黑色
2. 将叔节点设为黑色
3. 将祖父节点设为红色
4. 将祖父节点设为当前节点(之后继续对当前节点操作)
情况2
状态:(父节点是左子节点)当前节点的父节点是红色,叔节点是黑色,且当前节点是其父节点的右孩子
解决方案:
1.将父节点作为新的当前节点
2.以新的当前节点为支点进行左旋
情况3
状态:(父节点是左子节点)当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子
解决方案:
1.将父节点设为黑色
2.将祖父节点设为红色
3.以祖父节点为支点进行右旋
情况4
状态:(父节点是右子节点)当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子
解决方案:
1.将父节点作为新的当前节点
2.以新的当前节点为支点进行右旋
情况5
状态:(父节点是右子节点)当前节点的父节点是红色,叔节点是黑色,且当前节点是其父节点的右孩子
解决方案:
1将父节点设为黑色
2.将祖父节点设为红色
3.以祖父节点为支点进行左旋
二、代码
1.当前点的父节点为左子节点
使用解决方案:情况1 else (情况2 + 情况3)
rbtree_node * y = z->parent->parent->right;//z父节点的兄弟节点
if (y->color == RED){
//情况1
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}else{
if (z == z->parent->right){
//情况2
z = z->parent;
rbtree_left_rotate(T, z);
}
//情况3
z->parent->color = BLACK;
z->parent->parent->color = RED;
rbtree_right_rotate(T, z->parent->parent);
}
2.当前点的父节点为右子节点
使用解决方案:情况1 else (情况4 + 情况5)
rbtree_node *y = z->parent->parent->left;
if (y->color == RED){
//情况1
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}else{
if (z == z->parent->left){
// 情况4
z = z->parent;
rbtree_right_rotate(T, z);
}
//情况5
z->parent->color = BLACK;
z->parent->parent->color = RED;
rbtree_left_rotate(T, z->parent->parent);
}
总结
第一步:如果插入点的父节点是黑色,则不需要往下执行,如果插入点的父节点是红色,继续执行
第二步:如果叔节点是红色,直接变色,把祖父节点作为当前节点
第三步:
左(父节点相对祖父节点位置)右(当前节点相当于父节点的位置)为先左旋 然后 右旋
左左为 右旋
右右为 左旋
右左为 右旋 然后 左旋