一.维护红黑树的五条性质
红黑树与AVL树一样都是一颗自平衡二叉树,都能自主达到平衡。AVL树的平衡是判断左右子树的高度差的绝对值是否小于1.而红黑树的平衡只需保证它的以下几个性质达到满足即可: 1.节点是RED或者BLACK 2.根节点是BLACK节点 3.不能出现连续两个红色节点(可以出现连续两个黑色节点) 4.RED节点的子节点和父节点都是BLACK 5. 从任一节点到叶子节点的所有路径都包含相同数目的 BLACK 节点 6.叶子节点都是BLACK,(问上图叶子节点看着不全是黑色?答:这里所说的黑色节点是假想的黑色节点)
上面这几个性质不难理解,那么有人问了,为什么满足这几个性质就一定是平衡的?
从b树角度便可以很容易理解这个问题,因为红黑树等价于四阶b树,满足那几个性质的树就是一个红黑树,等价于四阶b树,b树一定是平衡的。
二、红黑树与四阶b树的等价变换
1.黑色节点与它的红色子节点合并看成一个b树节点,红黑树就类比转化成为了一颗b树。 2.红黑树的 BLACK 节点个数 与 4阶B树的节点总个数 相等
三.简单的继承关系
具体代码细节可移步代码仓库—>代码仓库
四.重新定义红黑树节点
理清亲子关系
public static class RBNode<E>extends Node<E>{
boolean color=RED;
public RBNode(E element, Node<E> parent) {
super(element, parent);
}
public Node<E> sibling()
{
if(isLeftChild())
{
return parent.right;
}
if(isRightChild()){
return parent.left;
}
return null;
}
@Override
public String toString() {
String str="";
if(color==RED){
str="R_";
}
return str+element.toString();
}
}
为什么默认为红色:因为默认为红色的情况下对于红黑树的几个条件除了出现连续红色节点可能不满足,其余条件都满足,所以更加的适合将红色设置为默认颜色.
因为默认为红色节点,并且要规避连续两个红色的情况.所以添加的时候需要对所有可能添加的位置进行分类,添加节点的父节点为黑色时无需处理直接添加即可,如果添加节点的父节点是红色,则应该按情况处理双红的局面
四.红黑树添加后的调整
有 4 种情况满足红黑树的性质 4 :parent 为 BLACK 同样也满足 4阶B树 的性质 因此不用做任何额外处理 剩余8个可以添加的位置,是不符合红黑树性质的—>会出现连续红色的现象.需要对其进行修复。这八种又分为两种,有四种会发生B树节点上溢的情况。 咱们先看不需要解决上溢的四种情况:🤩
1. 不会发生上溢 情况
(1)LL与RR情况
解救方案:将parent染成黑色,grand染成红色,然后进行旋转(LL进行右旋转,RR进行左旋转)
(2)LR与RL情况
- 自己染成 BLACK ,grand 染成 RED
- 进行双旋操作
3.LR:parent 左旋转, grand 右旋转 4.RL:parent 右旋转, grand 左旋转
2. 会发生上溢情况
10为红色节点,肯定不会单独成为一颗子树,一定会向上合并,一旦合并,对于四阶B树节点,达到四个元素就会发生上溢,其余三种情况也是如此
LL情况 类比上一节的B树,当B树节点发生上溢后的解决办法为 (找出节点的中间元素向上合并,然后中间元素两边元素分裂为两个子树。)
所以解决办法为,将parent,uncle节点染成黑色,grand节点染成红色,grand节点向上合并(当作新添加的节点,重复利用代码)。 ? grand 向上合并时,可能继续发生上溢 ? 若上溢持续到根节点,只需将根节点染成 BLACK
RR情况
- parent、uncle 染成 BLACK
- grand 向上合并
- 染成 RED ,当做是新添加的节点进行处理
LR,RL情况 解决方法同上面一样 添加调整代码
@Override
protected void afterAdd(Node<E> node) {
Node<E> parent=node.parent;
if(parent==null){
black(node);
root=node;
return;
}
if(isBlack(parent))
{
return;
}
Node<E> uncle=parent.sibling();
Node<E> grand=parent.parent;
if(isRed(uncle)){
black(parent);
black(uncle);
afterAdd(red(grand));
return;
}
if(parent.isLeftChild())
{
if(node.isLeftChild()){
black(parent);
red(grand);
}else {
black(node);
red(grand);
rotateLeft(parent);
}
rotateRight(grand);
}else{
if(node.isRightChild())
{
black(parent);
red(grand);
}else{
black(node);
red(grand);
rotateRight(parent);
}
rotateLeft(grand);
}
}
五.四.红黑树删除后的调整
删除代码过繁杂,可以移步代码仓库的删除代码逻辑梳理图解–>gitee代码仓库
删除后调整代码
@Override
protected void afterRemove(Node<E> node, Node<E> replacement) {
if(isRed(node)){
return;
}
if(isRed(replacement)){
black(replacement);
return;
}
Node<E> parent=node.parent;
if(parent==null)
{
return;
}
boolean left=parent.left==null||node.isLeftChild();
Node<E> sibling=left?parent.right:parent.left;
if(left){
if(isRed(sibling)){
black(parent);
red(sibling);
rotateLeft(parent);
sibling=parent.right;
}
if(isBlack(sibling.left)&&isBlack(sibling.right)){
boolean parentBlack=isBlack(parent);
black(parent);
red(sibling);
if(parentBlack){
afterRemove(parent,null);
}
}else {
if(isBlack(sibling.left)) {
rotateLeft(sibling);
sibling = parent.left;
}
color(sibling,iscolor(parent));
black(parent);
black(sibling.left);
rotateRight(parent);
}
}else {
if(isRed(sibling)){
black(parent);
red(sibling);
rotateRight(parent);
sibling=parent.left;
}
if(isBlack(sibling.left)&&isBlack(sibling.right)){
boolean parentBlack=isBlack(parent);
black(parent);
red(sibling);
if(parentBlack){
afterRemove(parent,null);
}
}else {
if(isBlack(sibling.left)) {
rotateLeft(sibling);
sibling = parent.left;
}
color(sibling,iscolor(parent));
black(parent);
black(sibling.left);
rotateRight(parent);
}
}
红黑树整体代码
package Tree;
import java.util.Comparator;
public class RBTree<E> extends BBST<E> {
public static final boolean RED=false;
public static final boolean BLACK=true;
public RBTree() {
this(null);
}
public RBTree(Comparator<E> comparator) {
super(comparator);
}
@Override
protected void afterAdd(Node<E> node) {
Node<E> parent=node.parent;
if(parent==null){
black(node);
root=node;
return;
}
if(isBlack(parent))
{
return;
}
Node<E> uncle=parent.sibling();
Node<E> grand=parent.parent;
if(isRed(uncle)){
black(parent);
black(uncle);
afterAdd(red(grand));
return;
}
if(parent.isLeftChild())
{
if(node.isLeftChild()){
black(parent);
red(grand);
}else {
black(node);
red(grand);
rotateLeft(parent);
}
rotateRight(grand);
}else{
if(node.isRightChild())
{
black(parent);
red(grand);
}else{
black(node);
red(grand);
rotateRight(parent);
}
rotateLeft(grand);
}
}
@Override
protected void afterRemove(Node<E> node, Node<E> replacement) {
if(isRed(node)){
return;
}
if(isRed(replacement)){
black(replacement);
return;
}
Node<E> parent=node.parent;
if(parent==null)
{
return;
}
boolean left=parent.left==null||node.isLeftChild();
Node<E> sibling=left?parent.right:parent.left;
if(left){
if(isRed(sibling)){
black(parent);
red(sibling);
rotateLeft(parent);
sibling=parent.right;
}
if(isBlack(sibling.left)&&isBlack(sibling.right)){
boolean parentBlack=isBlack(parent);
black(parent);
red(sibling);
if(parentBlack){
afterRemove(parent,null);
}
}else {
if(isBlack(sibling.left)) {
rotateLeft(sibling);
sibling = parent.left;
}
color(sibling,iscolor(parent));
black(parent);
black(sibling.left);
rotateRight(parent);
}
}else {
if(isRed(sibling)){
black(parent);
red(sibling);
rotateRight(parent);
sibling=parent.left;
}
if(isBlack(sibling.left)&&isBlack(sibling.right)){
boolean parentBlack=isBlack(parent);
black(parent);
red(sibling);
if(parentBlack){
afterRemove(parent,null);
}
}else {
if(isBlack(sibling.left)) {
rotateLeft(sibling);
sibling = parent.left;
}
color(sibling,iscolor(parent));
black(parent);
black(sibling.left);
rotateRight(parent);
}
}
}
@Override
protected Node<E> createNode(E element, Node<E> parent) {
return new RBNode<>(element,parent);
}
private Node<E> color(Node<E> node,boolean color){
if(node==null)
{
return null;
}
((RBNode<E>)node).color=color;
return node;
}
public Node<E> red(Node<E> node)
{
return color(node,RED);
}
public Node<E> black(Node<E> node)
{
return color(node,BLACK);
}
private boolean iscolor(Node<E> node)
{
return node==null?BLACK:((RBNode<E>)node).color;
}
public boolean isRed(Node<E> node)
{
return iscolor(node)==RED;
}
public boolean isBlack(Node<E> node){
return iscolor(node)==BLACK;
}
public static class RBNode<E>extends Node<E>{
boolean color=RED;
public RBNode(E element, Node<E> parent) {
super(element, parent);
}
public Node<E> sibling()
{
if(isLeftChild())
{
return parent.right;
}
if(isRightChild()){
return parent.left;
}
return null;
}
@Override
public String toString() {
String str="";
if(color==RED){
str="R_";
}
return str+element.toString();
}
}
}
|