红黑树的概念
红黑树,是一种二叉搜索树,但在每个节点上增加一个存储位表示节点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
红黑树的性质
性质一:根节点和所有外部节点都是黑色;
性质二:在根到外部节点的路径上,没有连续两个红色节点;
性质三:所有根到外部节点的路径上黑色节点的数目都相同;
举个简单红黑树的例子,如图
①可以看出根节点 6 和外部节点都是黑色满足性质一;
②红色节点4 的双亲节点和子节点都为黑色,满足没有连续的两个红色节点,满足性质二;
③红色节点4 的左右孩子节点到根节点的路径上黑色节点数都为3个,5的右孩子到根节点的路径上的黑色节点也为三个,8的左右孩子到根节点的路径上的黑色节点也为3,因此满足性质三;
红黑树插入节点
首先考虑插入的新节点应该是什么颜色的?
第一种情况:插入的所有新节点都是黑色
如图,例如,在之前的例子上插入3;可以看3的左右孩子到根节点的路径上有四个黑色节点,与其他外部节点到根节点的路径上有三个黑色节点不同,所以不满足性质三。其实可以推出不管在哪个外部节点插入一个黑色节点都不满足性质三。
那么再来看看第二种情况:插入的所有新节点都是红色
第二种情况又分为两种小情况
①插入节点的父节点颜色为黑色,如图
如图可见,满足红黑树要求,可以不做调整。
②当插入节点的父节点为红色时,如图
由图可以一眼看出有两个红色节点连在一起了,因此不满足性质二,要对其进行调整
根据两种情况对比,我们可知第一种情况当插入新节点都为黑色时,性质三一定被破坏,一定要对其做出调整,而第二种情况插入新节点都为红色时,如果插入的父节点为黑色则不需要做出调整,当插入的父节点为红色时才要做出调整。
因此,我们插入新节点为红色更为方便。
红黑树插入节点后如何调整?
- 父节点是黑色时,不做调整
- 父节点是红色时,如何调整?
- 我们将其划分为八种情况,首先我举个例子我是如何划分为的
我们举个LLr型的例子:
第一个L:代表插入节点的父节点是左孩子
第二个L:代表插入节点是左孩子
第三个r:代表插入节点u的叔叔节点是红色(red)
因此根据这样的规律XXx划分,可以划分为八种,而LXx(四种)和RXx(四种)仅仅只是方向相反,处理方法一模一样,因此接下来主要介绍如何处理LXx(四种)情况。
①LLr型
- 将pu变为黑色
- y变为黑色
- gu变为红色
- 为防止gu的父节点也为红色,将gu变为u,如果gu父亲节点为红色,则继续对其进行调整。
调整后为
符合红黑树三性质
②LRr型
- 将pu变为黑色
- y变为黑色
- gu变为红色
- 为防止gu的父节点也为红色,将gu变为u,如果gu父亲节点为红色,则继续对其进行调整。
调整后为
符合红黑树三性质。
由以上两种类型可以看出当y(插入节点的叔叔节点)为红色时,也就是XXr型,只需简单的对红黑树进行变换颜色就能使其继续满足红黑树性质。那么接下来看看当y为黑色时,如何调整红黑树。
③LLb型
- pu变为黑色
- gu变为红色
3.对gu进行右旋(和之前AVLTree一样)
满足红黑树三性质
④LRb型
- 将pu变成u
- 对u进行左旋
如图可以看出LRb型经过旋转后变成了LLb型,因此对其进行和LLb型一样的调整即可。
3.将pu变为黑色
4.gu变为红色
5.对gu进行右旋
最后调整为
红黑树删除节点
由于红黑树是基于二叉搜索树的进化,因此红黑树删除节点也是基于二叉搜索树。
其中我们先回顾一下二叉搜索树删除节点分为两种情况:
- 只有一个孩子,或者,是叶子节点。
- 有两个孩子
首先第一种情况:删除的节点是叶子或者只有一个孩子
第一张图是删除红色节点35,其为叶子节点,直接删除即可
第二张图是删除红色节点30,它有一个孩子节点,因此删除30后,将35节点上移代替30节点即可
删除后,如下图
再看下第二种情况:删除节点有两个孩子——>找要删除节点的后继节点(前驱)
它也分为两种情况
第一种情况
将该树中序遍历得:5,10,13,15,17,20,30,35,可以得知20的后继节点为30,删除20后,30代替20的位置
第二种情况
将该树中序遍历得:5,10,13,15,17,20,28,30,35,可以得知20的后继节点为28,删除20后,28代替20的位置
再回到红黑树删除节点,当红黑树删除红色节点
要删除红色节点20,20的后继节点为30,删除20,30代替20的位置,35代替30节点,颜色不改变。
满足红黑树三性质。
要删除红色叶子节点35时,直接删除。
满足红黑树三性质,因此得出结论红黑树删除红色节点,不会破坏红黑树的性质。
红黑树删除黑色节点
u:当前要删除的节点
x:是u的后继节点,也就是接替u的节点
y:接替x的节点(一般是x的左孩子或右孩子)
如果u为叶子节点,那么x和y都是null
删除黑色节点的几种情况
u x y
①黑色 红色 黑色
②黑色 黑色 红色
③黑色 黑色 黑色
首先看第①种情况 黑 红 黑
删除黑色节点u(15),后继节点x(17)代替u的位置,结果如图
可以看出删除了黑色节点后,按二叉搜索树的方法补齐即可,不需要改变颜色
那么再来看看第②种情况 黑 黑 红
删除黑色节点u(25),后继节点x(30)代替u的位置
变换后可见该树并不满足红黑树性质三,因此将y变为黑色
改变后如下
最后来第③种最复杂的情况 黑 黑 黑
其也分为几种情况
一
删除u(40)后,其后继节点x(50)代替其位置,与二叉搜索树的删除操作一样,调整之后还是满足红黑树性质。
二
删除u节点后得到
y为删除后的空节点
py为y的父亲节点
v为y的叔叔节点
删除u后又可以分为四种情况:
2.2 Rb 2.2 Rr 2.3 Lr 2.4 Lb
其中以Rb为例, R代表的是y是左孩子还是右孩子,R为右孩子,L为左孩子,r 表示的是兄弟节点的颜色,r表示的是红色,b表示的是黑色,由于Rx的情况和Lx的情况处理对称,因此本文之讲解Rx的情况。
在Rx的情况中,Rr的情况处理方式,是先将Rr转换为Rb,然后再用Rb的方式解决,因此Rb的处理格外重要
Rb又要再细分为三种情况Rb0、Rb1、Rb2,
- Rb0
0 代表v的左右孩子都为黑色,py可能不是根节点只是一个子树,则py可能为红色,因此调整Rb0,使Rb0恢复红黑树的性质应该:
- py变为黑色
- v变红
- py变为y,继续向上检查
②Rb1的第一种情况
变色
- v的颜色,变为py的颜色
- py的颜色变为黑色
- v的左孩子变为黑色
4.旋转右旋
Rb1的第二种情况
变色
- v的颜色,变为py的颜色
- py的颜色变为黑色
- v的左孩子变为黑色
- 旋转右旋
③Rb2
将Rb2转换为Rb1,再用Rb1的方式处理
变色
- 将v变红
- 将vr变黑
3.对v进行左旋
变色
4.v的颜色,变为py的颜色
5.py的颜色,变为黑色
6.v的左孩子变为黑色
7.对py右旋
那么现在所有的Rb情况的介绍完了,开头讲过所有Rx的情况中,Rr的情况处理方式,是先将Rr转换为Rb,然后再用Rb的方式解决,那么现在来看看Rr情况。
Rr型——>要变为Rb型
变色
- v变为黑色
- py变为红色
3.py进行右旋
可以看出
这一部分为Rb型,对该部分进行Rb操作,py变黑,20节点变红。
最后得到
红黑树和AVL树的比较
红黑树和AVL树都是常见的自平衡二叉搜索树,它们都能够保证树的高度不会过高,从而保证了树的查询、插入和删除操作的时间复杂度都是O(logN)。但是它们之间有一些不同点。
上面提到,红黑树是近似平衡,而AVL树是绝对平衡,因此,红黑树的查找效率低于AVL树。那么这对使用红黑树的影响大吗?那么需要探讨一下近似平衡的概念。
- 近似平衡
- 红黑树通过对从根到叶子节点的任一条路径上各个节点的着色方式的限制,以达到近似平衡的效果,即最长路径长度不超过最短路径的二倍。近似平衡,通俗理解,在效率方面,越接近平衡越优,越不平衡越差,若要得到其查找的时间复杂度,就要分近似平衡的最优情况和最差情况讨论。
- 最优情况:每条路径都是全黑,或者每条路径都是一红一黑相间。此时的红黑树是满二叉树,即最平衡的情况,查找的时间复杂度为O(logN)
2.最差情况:每个节点的往左右的两条路径,一条全黑,一条一红一黑相间,此时左右两条路径有一条是另一条的两倍,这种情况下为最差情况。抽象示意图如下:
⭕分析:
设全黑路径长度(即最短路径长度):h
极端情况下,当N黑很大时,N红相对于N黑很小,可忽略不计
N = N黑 + N红
故 N = N黑
此时只考虑黑色节点,可以想象成将红色节点都往最底部挪,那么上层是一个由黑色节点组成的满二叉树
故:N黑 = N = 2^h-1
h = logN
因为:全黑路径长度 = 最短路径长度 = h
所以:最长路径长度 = 2×最短路径长度 = 2h = 2logN
��红黑树最差情况的查找,就是去找最长路径的最后一个节点,综上推论,大概要找2logN次。而在AVL树中,由于绝对平衡的结构,查找一个节点只需找logN次。
给一个很大的数,比方说10亿。那么,在一棵10亿节点的AVL树中,查找的最坏情况是找30次(log10亿)。而在一棵10亿节点的红黑树中,查找的最坏情况是找60次(2*log10亿)。可见,红黑树的查找效率略低于AVL树,但是二者是同一个量级的,对于计算机来说,这点差别不算什么。所以这点效率区别对红黑树的使用影响并不大。
对于树的插入和删除。AVL树在插入或删除节点时,可能会需要更多地通过旋转操作来保持树的平衡,而旋转操作可能会导致更多的旋转,从而导致插入和删除操作的时间复杂度可能会比红黑树更高。而红黑树通过着色和旋转操作来保持平衡,旋转次数比AVL树少。因此红黑树插入和删除操作的效率可能会更高。
��得出结论:如果需要频繁进行插入和删除操作,且对查询效率要求不是特别高,可以选择红黑树;如果对查询效率有比较高的要求,且能够容忍插入和删除操作的效率稍低,可以选择AVL树。实际应用中,红黑树用的更多。