需要了解的点
1.二叉查找树
2.自平衡的二叉查找树
红黑树定义
红黑树是二叉查找树,但它教与二叉查找树难的地方在于,他是可以自平衡的二叉查找树:即在进行插入和删除等可能会破坏树的平衡的操作时,它可以重新自处理达到平衡状态。所以为了实现这个功能,它需要具备以下特性:
1.每个节点要么是黑色,要么是红色。
2.根节点是黑色。
3.每个叶子节点(NIL)是黑色。
4.每个红色结点的两个子结点一定都是黑色。
5.任意一结点到每个叶子结点的路径都包含数量相同的黑结点。
所以由以上性质推理:
1.如果一个结点存在黑子结点,那么该结点肯定有两个子结点。
2.红黑树并不是一个完美平衡的二叉查找树,因为如果左子树中存在红节点,为了保持平衡,就需要多一层节点,这样左子树就会比右边高,但黑节点的层数是相同的。所以红黑树这种平衡应该为黑色完美平衡。
红黑树怎样达到平衡,需要靠3种操作:
左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。
右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。
变色:结点的颜色由红变黑或由黑变红。
总结:感觉就是,左旋的时候,右边的子节点依次向上,替换旋转节点的位置,右子节点的左子节点变为旋转节点的右节点,反之亦然。其实他们的节点值并没有改变。如下图:

由上图可以看出:
1.左子树上的所有节点的值均小于或等于他的根节点的值
2.右子树上的的所有节点的值均大于或等于他的根节点的值
3.左右子树一定也是二叉排序树
4.即使左右旋他的值也是不变的
上图可以看出,右旋后的红黑树并不是平衡的,因为4如果是根节点的话,不能为红色,就需要再次变色或者旋转等操作以达到平衡。
如果你要对红黑树进行操作,通常我们要了解以下操作:
红黑树查找
因为红黑树是一颗二叉平衡树,并且查找不会破坏树的平衡,所以查找跟二叉平衡树的查找无异,它是按照值的大小进行查找的:
1.从根结点开始查找,把根结点设置为当前结点;
2.若当前结点为空,返回null;
3.若当前结点不为空,用当前结点的key跟查找key作比较;
4.若当前结点key等于查找key,那么该key就是查找目标,返回当前结点;
5.若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤2;
6若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤2;
由于红黑树总保持黑色完美平衡,所以它的查找最坏时间复杂度为O(2lgN),也即整颗树刚好红黑相隔的时候。能有这么好的查找效率得益于红黑树自平衡的特性,而为达到这个性能红黑树的插入必不可少:
红黑树插入
插入操作包括两部分工作:一查找插入的位置;二插入后自平衡。查找插入的父结点很简单,跟查找操作区别不大:
1.从根结点开始查找;
2若根结点为空,那么插入结点作为根结点,结束。
3.若根结点不为空,那么把根结点作为当前结点;
4。若当前结点为null,返回当前结点的父结点,结束。
5.若当前结点key等于查找key,那么该key所在结点就是插入结点,更新结点的值,结束。
6。若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤4;
7.若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤4;
那插入结点是什么颜色呢?红色。理由很简单,红色在父结点(如果存在)为黑色结点时,红黑树的黑色平衡没被破坏,不需要做自平衡操作。但如果插入结点是黑色,那么插入位置所在的子树黑色结点总是多1,必须做自平衡。还有一种情况,插入结点的父节点为红色时就会比较麻烦,会有三种情况需要处理,这时候就需要通过旋转和变色以达到自身的平衡。
红黑树删除
红黑树最复杂的操作就是删除了:
红黑树的删除操作也包括两部分工作:一查找目标结点;而删除后自平衡。查找目标结点显然可以复用查找操作,当不存在目标结点时,忽略本次操作;当存在目标结点时,删除后就得做自平衡处理了。删除了结点后我们还需要找结点来替代删除结点的位置,不然子树跟父辈结点断开了,除非删除结点刚好没子结点,那么就不需要替代。
二叉树删除结点找替代结点有3种情情景:
情景1:若删除结点无子结点,直接删除
情景2:若删除结点只有一个子结点,用子结点替换删除结点
情景3:若删除结点有两个子结点,用后继结点(大于删除结点的最小结点)替换删除结点
后继点为紧随其后的店,如上图的排序。
注意的是,替换点换到删除点位置时,如果替换点是红丝,一般不会影响平衡,则不需要做太多操作,只需要把替换点的颜色换成删除点颜色即可,但如果替换点时黑色,删除的话会影响其平衡,这时,就需要考虑平衡问题,要经过不同的旋转操作来达到新的平衡 。
参考连接:30张图带你彻底理解红黑树