目录
1.红黑树(Red Black Tree)
在1972年由Rudolf Bayer发明的。查找,插入和删除的时间复杂度都是O(log n)。n是节点的数目。红黑树不是严格意义上的平衡二叉树(AVL),但是总体的性能高于AVL树。红黑树在实际运用中也比较多。
2.性质:
- 性质1. 节点是红色或黑色。
- 性质2. 根节点是黑色。
- 性质3.所有叶子都是黑色。(叶子是NUIL节点)
- 性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
- 性质5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
由以上性质可以推断出从根到叶子的最长的可能路径不多于最短的可能路径的两倍
推导过程:
【假设每一条路径上的黑色节点个数为3个,则从根到叶子节点的最短路径长度为3。当黑色节点和红色节点交替出现,则形成从根节点到叶子结点的最长路径,路径长度为6(如下图)。所以,从根节点的最长的路径最多是最短的路径的两倍。
假设黑色节点数为n,则最短路径Lmin=n,最长路径Lmax=2n。假设其中的任意两条路径L1和L2且L1≤L2,则1≤L2/L1≤Lmax/Lmin=2n/n=2,即L2/L1小于等于2。所以从根到叶子的最长的可能路径不多于最短的可能路径的两倍】
3.插入操作
我们首先要知道,我们插入的节点默认是红色节点。那为什么是红色节点而不是黑色节点呢?
假设插入的节点默认是黑色节点。插入节点前是一棵红黑树,满足红黑树的性质(每条路径上黑色节点的数目相同)。如果插入节点,插入节点位置一定是叶子节点。插入节点后,从根节点到插入节点路径上黑色节点的数目一定比其他从根节点到其他叶子结点的路径长度大1。此时,不满足红黑树的性质,所以要进行红黑树的调整。一条路径黑色节点的数目和剩余所有路径黑色节点数目不同,调整可能需要调整所有路径,调整的难度比较大。
假设插入的节点默认是红色节点,将该节点称为子节点。如果父节点为黑色,则此树不用做任何调整,也满足红黑树的性质。如果父节点为红色,要继续判断父节点的兄弟节点为红色节点还是黑色节点,然后在进行调整。
整体来说,默认节点是红色节点比黑色节点调整难度小。所以选择默认节点是红色节点。
下面是进行插入操作时,详细的分类和操作步骤。操作步骤分为两步:旋转和变色。
情况1:插入的节点为红色节点cur,其父节点parent为黑色节点。根据插入的位置,4种情况,如下图。
操作步骤:不进行操作
情况2:插入的节点为红色节点cur,其父节点parent为红色节点。父节点的父节点为grandpa,grandpa节点必为黑色节点【因为parent节点为红色节点,相邻的两个节点不能同为红色,所以grandpa节点必为黑色】。父节点的兄弟节点为cur节点的uncle节点,uncle节点的颜色分为2种情况,黑色or红色。
情况2.1:uncle节点为红色节点。根据cur节点插入的位置,分为4种情况(1),(2),(3),(4)。
操作步骤:将parent节点和uncle节点变成黑色,将grandpa节点变成红色。如果grandpa节点为根节点,则将grandpa节点变成黑色。
情况2.2:uncle节点为黑色节点或者为null。根据cur节点插入的位置,分为4种情况(1),(2),(3),(4)。
【注意:出现该情况一定是情况2.1调整后的结果。如左下图。如果cur是新插入的节点,节左边路径只有1个黑色节点,而右边路径有2个黑色节点。违反红黑树性质,所以,cur节点不是新插入的节点。从情况2.1调整后的红黑树,可以看到最上面的grandpa节点是红色的。所以,情况2.2有可能在情况2.1调整后出现。较为完整的树结构为右下图】
操作步骤:
1.将grandpa节点,parent节点,cur节点看做非平衡二叉树,将他们调整为AVL树(平衡二叉树)。【有4种旋转调整方式(见博客https://blog.csdn.net/qq_21388535/article/details/105588488)】
2.调整完后,将第二层节点上升到第一层节点的那个节点的颜色由红色变成黑色。将第一层节点下降到第二层节点的颜色由黑色变成红色。【这里的第一层,第二层是下图中局部的第一层,第二层。并且是最后一次调整的结果。比如进行LR旋转,则是在R旋转后进行变色。】
该种情况可能有4种方式:
定义:如果parent为grandpa的左孩子,cur为parent的左孩子,则grandpa,parent,cur的位置关系为左左。其他类似。
uncle节点的虚线代表,uncle节点可以存在,或者为null。
(1)LL
(2)LR
(3)RL
(4)RR
总结:
插入节点为cur,cur的父节点为parent,parent的父节点为grandpa,parent的兄弟节点为cur的uncle。
1.插入的节点默认是红色的。
2.如果parent为黑色,不进行调整。
3.如果parent为红色,uncle为红色,则将parent和uncle的颜色都变为黑色。grandpa的颜色变为红色。如果grandpa为根节点,再将grandpa的颜色变为黑色。
4.如果parent为红色,uncle为黑色。先进行旋转操作,在进行变色操作。旋转操作和AVL的4种方式一样。变色操作:在完成最后一步旋转操作时,成为顶点的节点颜色变成相反的颜色——黑色;由顶点变成下一层节点的颜色变成相反的颜色——红色。