红黑树简单解析,动画演示

今天我们来了解下红黑树。

1、啥是红黑树?

红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。因此想要弄清楚红黑树,我们需要先解决几个问题:
① 二叉查找树是什么?
② 为什么会出现红黑树?

2、剖析二叉查找树

二叉查找树特性
二叉查找树(Binary Search Tree)是一颗二叉树,简称BST。就像我们说int都是整数一样,BST这一种二叉树需要满足如下三个特性:
① 某节点的左子树节点值仅包含小于该节点值
② 某节点的右子树节点值仅包含大于该节点值
③ 左右子树每个也必须是二叉查找树

长啥样?在线演示BST网址:cs.usfca.edu/~galles/visualization/BST.html

ps:这个网站不只二叉树,绝大部分算法的增删改查都可以去演示,是理解算法的好帮手,强烈建议保存!

BST在理想情况下是如下这样的:
在这里插入图片描述
当BST发生倾斜后是这样的:
在这里插入图片描述
在理想的情况下,二叉查找树增删查改的时间复杂度为O(logN)(其中N为节点数),最坏的情况下为O(N)。

怎么解决倾斜
通过以上两个相同数据的BST的演示,我们发现了一个问题,同样的数据组成,只是因为数据插入的先后顺序,就使得产生的二叉查找树发生了倾斜。
那么我们怎么解决这个问题呢?首先想到的就是每次插入或者删除数据的时候都进行判断,对已经存在的树结构进行旋转,使其维持在logN的高度上,这样不管我们按照什么样的顺序插入数据,最终的结构只要能满足logN的高度,那它的结构一定是理想状态下的。

红黑树产生
基于BST存在的问题,一种新的树——平衡二叉查找树(Balanced BST)产生了。平衡树在插入和删除的时候,会通过旋转操作将高度保持在logN。其中两款具有代表性的平衡树分别为AVL树和红黑树。AVL树由于实现比较复杂,而且插入和删除性能差,因此在实际环境中我们更多的是应用红黑树。

3、红黑树的用途及特性

用途
红黑树(Red-Black Tree)以下简称RBTree的实际应用非常广泛,比如Linux内核中的完全公平调度器、高精度计时器、ext3文件系统等等,各种语言的函数库如Java的TreeMap和TreeSet,C++ STL的map、multimap、multiset等,是函数式语言中最常用的持久数据结构之一。
由于在java8里HashMap的底层实现用RBTree取代链表,使得性能得到了提升,因此很多人才去关注或者深入学习红黑树。

特性
RBT树上的每个节点,都要遵循下面的规则:
① 每个节点都是红色或者黑色;
② 根节点必须始终是黑色;
③ 没有两个相邻的红色节点;
④对每个结点,从该结点到其子孙节点的所有路径上包含相同数目的黑结点。

RBT树在理论上还是一棵BST树,但是它在对BST的插入和删除操作时会维持树的平衡,即保证树的高度在[logN,logN+1](理论上,极端的情况下可以出现RBTree的高度达到2*logN,但实际上很难遇到)。这样RBTree的查找时间复杂度始终保持在O(logN)从而接近于理想的BST。RBTree的删除和插入操作的时间复杂度也是O(logN)。RBT的查找操作就是BST的查找操作。
上面的规则看一下有个印象就好,接下来是红黑树比较复杂的地方,就是红黑树的调整。

4、拒绝死记硬背,跟着动图理解调整算法

为了维持RBT的规则,RBT定义了两个重要的操作:
① rotation:旋转,这是树达到平衡的关键;
② recolor :重新标记黑色或红色。
4.1、 首先先看最基础的recolor,也就是第一种情况
先看如下gif:
在这里插入图片描述
小结一波:
通过上面动图,我们发现整个插入及调整一共是如下7步:
① 新插入的节点004标记为红色;
② 插入后发现004的父节点005也是红色,违反了RBT的规则3( 没有两个相邻的红色节点);
③ 发现004的叔父节点007同样是红色;
④ 使用recolor方法,把005和007也就是父节点和叔父节点标记为黑色;
⑤ 将004和它的祖父节点006标记为相同的颜色,也就是红色,往上递归重复步骤2,3;
⑥ 发现它的祖父节点是根节点,标记为黑色;
⑦ 调整完毕。
4.2、开始考虑旋转rotation方法,首先展示第二种情况:左旋
先看如下gif:
在这里插入图片描述
小结一波:
这里我们就不用再分步骤去看了,只需要知道整体的调整方式就行了;左旋就是当新加入节点之后,树的高度及颜色不再满足RBT定义的规则后;将不满足的节点进行左旋转,使得它取代之前它的父节点,同时它的父节点变为它的左子节点,最后应用第一种方法调整颜色的过程。

4.3、第三种情况:右旋
先看如下gif:
在这里插入图片描述
小结一波:
右旋就是以某节点为中心进行向右的旋转,取代并成为之前自己的父节点,然后把之前的父节点变为自己的右子节点,最后应用第一种方法调整颜色的过程。

5、总结

最后我们把实际使用中,或者研究HashMap源码时需要提前了解的红黑树调整规则整理总结一下:
为了方便记忆,我们取英文首字母,定义连续的三代节点,新增节点为N,父节点为P,叔父节点为U,祖父节点为G
在这里插入图片描述
红黑树看似复杂,其实只要我们理解了它的来源,定义的规则,为了完成规则使用的方法及三种调整策略,然后多加练习,多观察,就可以很容易的去掌握它的规律。

欢迎小伙伴们留言交流~~
浏览更多文章可关注微信公众号:diggkr

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页