本文讲解红黑树的内容是基于平衡二叉树,如果对平衡二叉树不熟悉的朋友可以先浏览上一篇文章
简单聊聊平衡二叉树搜索树 [ 红黑树基础 1/2] - 掘金 (juejin.cn)
1 红黑树的规则
先说红黑树的规则,听起来可能有点懵,先有个概念就好
-
① 既然是红黑树,所以节点要么是红节点,要么是黑节点
-
② 根节点一定是黑节点
-
③ 红黑树的叶子节点并非传统的叶子节点,意思是即使是叶子节点,其仍然拥有两个为null的子节点
-
④ 为null的叶子节点一定是黑节点,所以一半以上的节点都是黑节点
-
⑤ 红节点的下一个节点一定是黑节点
-
⑥ 新插入的节点是红节点, 但是经过后面的调整之后这个新插入的节点可能变为黑节点
-
⑦ 从任一节点出发到叶子节点经过的黑节点数必须是一样的(经过调整)
(此图来源CSDN作者 晓之木初 )
先下定义,红黑树也是一种“平衡二叉树”,但这种平衡二叉树没有avl那么严苛,不需要保证平衡因子的绝对值是小于1,而是需要保证当前树符合第⑦条规则。
分析第⑦条规则,可知两条路径的
上界是:两条路径都是只有黑节点并且两条路径的节点数相同
下界是:
假设一条路径都是黑节点3个,所以另一条路径上最多只有3个黑节点,又因为红节点的下一个节点必须是黑节点,所以是交错的,例如 (红-黑-红-黑-红-黑)。当第一个节点是红节点的时候,以交错的形式排开时候红节点数目最多,最多是3个(叶子节点必须是黑节点),所以一共有5个节点。
所以可以得到规律当一条路径上全是n个黑节点的时候,另一条路径上最多只有n个红节点,共有2n-1个节点。所以左右子树的深度相差不超过一倍。
与AVL的区别--面试常问,例如Java8中的HashMap的实现当桶中的链表达到八以上的时候就会从链表的结构转换成红黑树,那为什么不是转换成AVL或者BST呢?
由于AVL的平衡条件非常苛刻,导致需要调整的平均次数会多,从而效率降低。红黑树的这种条件就会降低调整的次数从而提高效率。
时间复杂度是 O(log n)。为什么呢?
求证过程如下:
N 为总节点数 , Nb 为黑节点数 , Nr 为红节点数,N = Nb + Nr
最差的情况是什么时候?最差的情况是下界这种红黑相间的时候。当我们盖住Nr不看,只看Nb的时候,该树就是一棵AVL,他的时间复杂度是 O(log Nb)。当加上Nr的时候,高度变成了 2*log Nb,时间复杂度是 O(2 * log Nb),也就是 O(log Nb)。而Nb是等于Nr,所以就是O(log n/2),也就是O((log n )-1),既O(log n )
2 红黑树的执行流程
根据上表的执行规则进行红黑树的插入。叔节点是指父节点的兄弟节点,类型是指从祖父节点到当前插入节点所走的路径类型。
Red/Black Tree Visualization (usfca.edu) 用于展示红黑树过程的一个网站
- 初始根节点是1 ,插入2后的效果,新插入的节点是红节点(规则⑥)
- 插入节点3,此时形成父节点是红节点,叔节点是黑节点(规则②、④),并且类型是右右,所以执行先左旋后变色
- 插入节点4,此时形成父节点是红节点,叔节点也是红节点,所以叔父都变黑,祖父变红,并且把祖父当作当前新插入的节点递归变色,因为此时祖父节点是根节点,所以变黑。
- 插入节点8,此时父节点是红色,叔节点是黑色,类型是右右,所以执行先左旋后变色,变色的时候尽量不更改新插入的红色节点的颜色,不然随着红色变黑色增加了那么红黑树的意义就不大了(个人理解)。
- 同理再插入一个 节点 10
- 插入节点9,此时父节点是红节点,叔节点是黑节点,类型是右左,所以先右旋再左旋,然后变色。右旋和左旋都是以父节点为轴节点进行旋转
其余情况以此类推
有不对的地方请指出,谢谢 开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天