您的位置:首页 > 其它

红黑树的由来,特性,原理以及适用场景分析

2018-11-16 15:12 337 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37264516/article/details/84138212

注意:本文不涉及红黑树的具体实现,并且默认读者已经对二叉树,二叉查找树,AVL 树等已经了解并熟悉。

一、平衡二叉查找树

定义:树中任意一个节点的左右子树高度差不大于 1。

AVL树
是一种严格按照定义来实现的平衡二叉查找树,所以,它的查找效率非常稳定,是
O(log n)
,由于严格按照左右子树高度差不大于一的规则,插入和删除操作中需要大量的操作来保持树的平衡,比较耗时。

因此,

AVL树
适用于大量查询,少量插入和删除的场景中。

思考一下,当插入一个数据或者删除一个数据时,什么样的操作能够将不平衡的二叉查找树继续保持平衡?

答案是左旋右旋


从图中可以观察到,右旋操作是将左子树高度减一,右子树高度加一(左旋反之),并且观察

α、β、γ
可以发现,旋转后依旧符合二叉查找树的特性。

二、红黑树

上一小节介绍了

AVL树
的优缺点以及平衡二叉树保持平衡的基本操作。

在分析

AVL树
后,发现其插入和删除操作复杂且效率不高,不适合应用于需要大量插入、删除和查找的场景。

思考:AVL 树是因为需要严格按照左右子树高度差不大于 1,导致插入删除时需要复杂的操作来维持树的绝对平衡,所以,是否可以通过降低对平衡性的要求,来提高插入删除的效率呢?

答案当然是可以的,红黑树正是这样产生的。

先来看一下一棵合格的红黑树需要满足什么样的要求:
1. 树中的节点有两种标记,红色节点和黑色节点;
2. 根节点为黑色;
3. 每个叶子节点都是空的黑色节点;
4. 两个红色节点不能相邻;
5. 每个节点,从它开始往叶子节点走的所有路径,每条路径都包含相同数量的黑色节点;

如图是合格的一棵红黑树,图中我省略了所有的黑色的叶子节点,可以自行验证是如何符合上述五个条件的:(例如:第五点,从根节点出发,到叶子节点,每条路径的黑色节点都是 4 个,包括空的叶子节点)

乍一看要求很多,而且像第三、第四点可能根本就不知道它为什么要这样设计,现在我们就来分析一下,为什么是这五个条件,他们分别起什么作用。

先说简单的,第一点,红黑树,顾名思义,节点有红有黑,不难理解,至于为什么要将节点区分红色和黑色,请继续往下看。

第二点和第三点,根节点为黑色,叶子节点为空,并且也是黑色,这样设计是为了方便红黑树代码实现,不懂的可以自行百度:通过哨兵简化代码的编写

最后,第四第五点是体现红黑树核心思想的两点,也是最不容易理解的两点。我们将通过推导红黑树的高度来理解这两点的作用。

三、红黑树的高度

二叉查找树的查找效率与树的高度直接相关。那么红黑树到底降低了多少对平衡的要求,并且查找效率究竟与 AVL 树相差多少呢。

我们可以先思考一下,既然红黑树并不严格符合左右子树高度差不大于 1 的规则,那么它的高度究竟是多少呢?我们可以通过推导来粗略的估算一下。

首先,我们将一棵红黑树的红色节点剔除,失去了父节点的黑色节点接到祖父节点上,如图:

我们可以发现,剔除红色节点后,剩余的黑色节点组成了一棵

四叉树
(二叉树每个节点最多两个子节点,因此,在剔除红色节点后,祖父节点最多挂四个子节点)

回忆一下红黑树的第五点要求:每个节点,从它开始往叶子节点走的所有路径,每条路径都包含相同数量的黑色节点,可以发现,因为这个要求的约束,黑色节点在树的垂直方向上是趋向于均匀分布的,因此上图形成的四叉树高度肯定比相同节点数的完全二叉树高度小。完全二叉树的高度是 log n 。

这个时候,我们再将红色节点添加到这棵四叉树中,再来回忆一下第四点要求:两个红色节点不能相邻,因此红色节点肯定是在两个黑色节点中间的,只要插入一个红色节点,那么对应的上下两个黑色节点从

2
层增加到
3
层,因此考虑将最大红色节点数插入这棵四叉树中时,最终这棵四叉树的高度变成了原来的 2 倍

最终,我们推导出红黑树的高度范围是

log n
2log n
内,由此可见,红黑树的查询时间复杂度依旧是
O(log n)

通过推导过程,我们可以发现,红黑树的红色、黑色节点,以及红黑节点遵守的规则,实际上是用来保证红黑树的高度不超过

2log n
,也就是用于避免左右子树高度差太大导致查询效率过低。

事实上红黑树的效率比我们推导的只会更高。

实际实现一棵红黑树,在插入删除元素后,维持红黑树的操作除了开始讲的左旋和右旋,还加入了节点颜色的转换,通过两者的结合,每次修复打破平衡的红黑树,只需要不超过 3 次旋转操作。

四、红黑树的适用场景

总结一下红黑树的特性:

  1. 红黑树是一颗近似平衡的二叉查找树
  2. 支持高效的查找、插入和删除元素
  3. 查找删除和插入的效率稳定

综合比较而言,红黑树更适合应对实际开发中的复杂场景。

由于红黑树的代码实现比较复杂,如果实际开发中需要手动实现红黑树,我们更推荐采用跳表。

最后,本文是基于极客时间专栏《数据结构和算法之美》,欢迎入坑学习。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: