一、概念
红黑树是一种自平衡二叉查找树(二叉排序树)。与平衡二叉树(avl树)不同的是,红黑树是弱平衡二叉树,即它的左右子树高度差有可能大于1,但不超过一倍。
二、5大性质
- 每个节点要么是黑色, 要么是红色。
- 根节点是黑色。
- 每个叶节点(Nil,空值)都是黑色。
- 每个红色节点的两个子节点一定都是黑色。(但黑色节点的子节点可以也是黑色)
- 任意一个节点到每个叶子节点的路径都包含相同数量的黑节点。
总结:根黑叶黑,红不相邻,黑色平衡。
三、推论(或规律)
- 左子树和右子树的黑节点的层数是相等的。因此我们称红黑树的这种平衡为黑色完美平衡。(由性质5推出)
- 如果一个节点存在黑子节点,那么该节点肯定有两个子节点。(由性质5推出)
- 任意节点到每个叶子节点最长路径不会超过最短路径的2倍。(由性质4、5推出)
- 任意节点到每个叶子节点的路径都有相同的黑节点个数。
- 树的高度不超过2log(n+1)。
四、红黑树的操作及其时间复杂度
时间复杂度:查询、插入和删除均为O(logn)。
关于红黑树的操作大家可以自己去在线演示网站试试:
中文版:https://rbtree.phpisfuture.com/
英文版:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
PS:英文版网站还有各种数据结构的在线演示哦:
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
口诀:叔红要变色,叔黑要左右;右子要左旋,左旋自己来;左子要右旋,右旋父亲去。
1、查询操作
2、变色操作
也就是把节点涂成黑色或红色。
3、插入操作
插入的新节点一定是红色,也就是“红插”,后续将根据平衡性变色。
同时由于是红插,插入操作只会破坏第4个性质,也就是“红不相邻”的性质;调整时才会破坏第2或第5个性质。
- 若插入新节点后依然满足红黑树定义,则插入结束
- 若插入新节点后不满足红黑树定义(非根节点只需要看是不是红相邻了,如果是根节点,涂黑即可),需要调整,看叔叔节点:
- 叔叔节点是黑色
- LL型:右单旋,父换爷+变色
- RR型:左单旋,父换爷+变色
- LR型:左右双旋,儿换爷+变色
- RL型:右左双旋,儿换爷+变色
- 叔叔节点是红色
4、删除操作
5、红黑树的建立
- 当插入节点的父亲节点为null,则将该节点颜色置为黑色。
- 当插入节点的父亲节点为黑色,不需要调整。
- 当插入节点的父亲节点为红色,其叔叔节点亦为红色,则将其父亲节点和叔叔节点置为黑色,同时将祖父节点置为红色,将祖父节点设置为当前新增节点,重新按照从规则1开始判断。
- 当插入节点的父亲节点为红色,其叔叔节点为黑色或null,则需要分多种情况考虑。
a. 新增节点为父亲节点右孩子,同时父亲节点是祖父节点的左孩子,则进行左旋,将父亲节点置为新节点,重新按照规则1进行判断;
b. 新增节点为父亲节点左孩子,同时父亲节点是祖父节点的右孩子,则进行右旋,将父亲节点置为新节点,重新按照规则1进行判断;
- 不满足上述所有条件,将父亲节点置为黑色,同时,将祖父节点置为红色,进行以下两种情况判断。
a. 新增节点为父亲节点左孩子,同时父亲节点是祖父孩子的左孩子,则对祖父节点进行右旋
b. 其他情况,对祖父节点左旋。
五、与平衡二叉树(avl树)的联系和差别
联系
- 都是自平衡二叉树
- 查找、插入和删除的平均时间复杂度相同( log 2 n \log_2n log2n)
- 高度都趋近于 log 2 n \log_2n log2n
差别
- 平衡二叉树都可以经过变色操作成为红黑树,但红黑树不一定是平衡二叉树。
- 平衡二叉树是严格平衡二叉树,红黑树是弱平衡二叉树。
- 红黑树的自平衡操作一定会在3次旋转之内解决,而平衡二叉树往往要比红黑树多。
- 因为平衡二叉树更平衡,查找效率往往要高于红黑树;但插入和删除效率往往低于红黑树。
- 实际应用中,若搜索次数远远大于插入和删除次数,那么选择平衡二叉树;否则,选择红黑树。
- 平衡二叉树的插入/删除操作很容易破坏“平衡”特性,需要频繁调整;红黑树的插入/删除操作相对不容易破坏“平衡”特性,不需要频繁调整。
六、应用
- 广泛用于C++的STL中,map和set都是用红黑树实现的。
- 著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块,进程的虚拟内存区域都存储在一颗红黑树上,每个虚拟地址区域都对应红黑树的一个节点,左指针指向相邻的地址虚拟存储区域,右指针指向相邻的高地址虚拟地址空间。
- IO多路复用epoll的实现采用红黑树组织管理sockfd,以支持快速的增删改查。
- ngnix中,用红黑树管理timer,因为红黑树是有序的,可以很快的得到距离当前最小的定时器。
- java中TreeMap的实现。
七、例题
1、红黑树与AVL树性质(自平衡、查找、插入、删除的时间复杂度)
2、为什么用红黑树不用二叉平衡树
3、证明每一棵AVL树都可以被涂成红黑树。所有的红黑树都是AVL树吗?
4、红黑树的插入算法复杂度最坏情况是
- A.O(n)
- B.O(log(n))
- C.O(nlog(n))
- D.其他都不对
解答:B。
5、关于红黑树和AVL树,以下哪种说法不正确?
- A. 两者都属于自平衡二叉树
- B. 两者查找,插入,删除的时间复杂度相同
- C. 包含n个内部节点的红黑树的高度是O(log(n))
- D. JDK的TreeMap是一个AVL的实现
解答:D。TreeMap是红黑树实现的。
6、 下面描述错误的是____。
- A.从任意节点出发的所有下降路径都有相同的黑节点个数
- B.从任意节点出发的所有下降路径都有相同的红节点个数
- C.该树的高度不超过2log(n+1)
- D.从某节点到其后代叶节点的所有简单路径中,最长的一条是最短一条的至多两倍
- E.从根到叶节点(不包含根)的任一条简单路径上至少有一半的节点必是黑色的
- F.在红黑树上的查找操作可以在O(logn)时间内完成
解答:B。红黑树是黑色完美平衡,并没有红色完美平衡的说法。
7、请你来说一说红黑树和AVL树的定义,特点,以及二者区别
8、关于红黑树,以下哪种说法是不正确的?
- A.一棵含有n个节点的红黑树的高度至多为2log(n+1)
- B.如果一个节点是红色的,则它的子节点必须是黑色的
- C.从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点
- D.红黑树的查询效率一般要优于含有相同节点的AVL树(平衡二叉树)
解答:D。红黑树查询效率低于AVL数,插入、删除效率高于AVL树。
9、采用插入方式构建一颗大小为n的红黑树的时间复杂度是多少?
- A. O(log(n))
- B. O(n)
- C. O(n*log(n))
- D. O(n^2)
解答C。
10、关于红黑树,下述说法错误的是_______.
- A. 红黑树是平衡的二叉树
- B. 红黑树是二叉搜索树
- C. 红黑树的高度为 O(logn)
- D. 红黑树插入和删除过程至多有 2 个旋转操作
解答:D。至多3个操作。
11、以下哪个数据结构底层是用红黑树实现的?
- A. vector
- B. list
- C. map(散列表+红黑树)
- D. deque
解答:C。
12、包含 8 个内部结点的红黑树中,最多可有几个红色结点,最少可有几个红色结点。
13、红黑树的插入复杂度为( )。
- A. O(n)
- B. O(1)
- C. O(n^2)
- D. O(log2(n))
解答:D。
14、红黑树在处理过程中红黑节点会产生冲突,请问在下列操作中解决的冲突中,正确的是
- A. 插入操作时,解决红黑冲突
- B. 删除操作时,解决黑黑冲突
- C. 插入操作时,解决红红冲突
- D. 删除操作时,解决黑黑冲突
解答:C。
15、证明:在一棵红黑树中,从某节点x到其后代叶节点的所有简单路径中,最长的一条至多是最短一条的2倍。
16、在一棵有 n 个关键字、高度为 h 的红黑树中,根的高度至少是多少?至多是多少?
17、在一棵黑高为k的红黑树中,内部节点最多可能有多少个?最少可能有多少个?
18、将关键字41,38,31,12,19,8连续地插入一棵初始为空的红黑树之后,试画出该节点树。
19、试描述一棵含有n个关键字的红黑树,使其红色内部结点个数与黑色内部结点个数的比值最大。这个比值是多少?该比值最小的数又是怎样呢?比值是多少?
20、考查含有2012个内部节点的红黑树。
a) 该树可能的最小黑高度 dmin 是多少?
b) 该树可能的最大黑高度dmax是多少?
c) 该树可能的最小高度 hmin 是多少?
21、证明红黑树的高度最多为2logN
22、为什么插入的节点一定是红色?红插有可能破坏红黑树的性质,也有可能不破坏,但黑插一定破坏性质5