红黑树中nil结点_漫画:什么是红黑树?

前言

017年,小灰曾经发布过一篇关于红黑树的漫画,当时由于时间仓促,部分知识点一带而过,并没有讲解得很细致全面。

最近,小灰把这个知识点重新做了总结,分成上下两篇,希望大家把红黑树这个重要的数据结构彻底吃透。

7fb4f4d2449e8aa6374fedd994bb83dc.png
73bbafe6596c445a5d201175bad32dc3.png

————— 第二天 —————

403536f9e6f48eb2ff5bd6b3166c8b0f.png
2c45222025a08aea68424e6e57ebcf77.png
0280d67158e1b79c95f355bc3b1f812a.png
c18f020f110e5a3e8855bef9ccaa93be.png
22b172ba57d009d290f4290a30a020f5.png
4251685959198c1fbd42093a81cdbe6d.png
fe57a233b477f5b6ff243fe6c5272bda.png

————————————

7102ed9d8a19086f4b408d19a94a241a.png
29eac5418687ecac445f01857127c9e2.png
27f02dae9324a3829dbadabb37e11b6e.png
87c63d9d63f145d34bdbd3244709c453.png

二叉查找树(BST)具备什么特性呢?

1.子树上所有结点的值均小于或等于它的根结点的值。

2.子树上所有结点的值均大于或等于它的根结点的值。

3.左、右子树也分别为二叉排序树。

下图中这棵树,就是一颗典型的二叉查找树:

a7d7845961da587077a5d708fc145b66.png
033b7493b16dcf280c4c8363d120052a.png

1.查看根结点9

309be69ab6522e3fca371753b65e9270.png

2.根据二叉查找树左子树小、右子树大的特性,10 > 9,因此值为10的结点只可能在根结点的右子树当中,我们查看右孩子结点13

014f89ddb30f13e77f04a4dcac08936f.png

3.由于10 < 13,因此查看左孩子11

147a78efa74512670389ddea69cb34c7.png

4.由于10 < 11,因此查看左孩子10,发现10正是要查找的结点:

2b9f57f7aabd111778219e2573b0045f.png
d3787a58c7993b50bc1bb9b163b62dfe.png
f2819739481f89dfc8a5b946f3c0aabb.png
f0b752157bb105df4ac49d54bf79ac13.png
0454a042cabdc9c20420d36024fe6c98.png
8782b14ae6086d10e9dd094b85deb0d7.png
d99df8728bc7b90360732ae21cab5d11.png
c2fa549c3d08a24c188ea9164eec250c.png

假设初始的二叉查找树只有三个结点,根结点值为9,左孩子值为8,右孩子值为12:

62b5601fc8be6e2a59a9af24fb28ae79.png

接下来我们依次插入如下五个结点:7,6,5,4,3。依照二叉查找树的特性,结果会变成什么样呢?

9eb9921c9880ab1df2cbf3634f33358b.png
443cd2afa804ed8438f3dbf02df1816a.png
3f0c1a89699ccc87995a70bd31cb4494.png
c2f585a1b5bf4787ce29b9fa4040d82e.png
ce59516f3003a6105964b58f909b6389.png

1.结点是红色或黑色。

2.根结点是黑色。

3.每个叶子结点都是黑色的空结点(NIL结点)。

4 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)

5.从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。

下图中这棵树,就是一颗典型的红黑树:

8a432dccc6e9e0bf202edff5f0f35ac3.png
0c09c5a1821b80723da553ee938ed350.png
b3214de4f3ed7279c29212647866dab9.png
efdbf21c848f2024b54a1b051dae6eeb.png

什么情况下会破坏红黑树的规则,什么情况下不会破坏规则呢?我们举两个简单的例子:

1.向原红黑树插入值为14的新结点:

dff6a56eeef86bd09e2ec05d91e50f77.png

由于父结点15是黑色结点,因此这种情况并不会破坏红黑树的规则,无需做任何调整。

2.向原红黑树插入值为21的新结点:

9534e89cf9c88ff3035513a480714527.png

由于父结点22是红色结点,因此这种情况打破了红黑树的规则4(每个红色结点的两个子结点都是黑色),必须进行调整,使之重新符合红黑树的规则。

643e2dcf80c6979eb34f7ca01bbda77b.png
36795e4c23b4b679d0b3ec45321e7531.png

变色:

为了重新符合红黑树的规则,尝试把红色结点变为黑色,或者把黑色结点变为红色。

下图所表示的是红黑树的一部分(子树),新插入的结点Y是红色结点,它的父亲结点X也是红色的,不符合规则4,因此我们可以把结点X从红色变成黑色:

5e5dbb73863ae24281cd2f2e76234e2a.png

但是,仅仅把一个结点变色,会导致相关路径凭空多出一个黑色结点,这样就打破了规则5。因此,我们需要对其他结点做进一步的调整,后文会详细说明。

左旋转:

逆时针旋转红黑树的两个结点,使得父结点被自己的右孩子取代,而自己成为自己的左孩子。说起来很怪异,大家看下图:

c838ca78e823542ee2b43e9830edfacc.png

图中,身为右孩子的Y取代了X的位置,而X变成了自己的左孩子。此为左旋转。

右旋转:

顺时针旋转红黑树的两个结点,使得父结点被自己的左孩子取代,而自己成为自己的右孩子。大家看下图:

0f36133a8b776b34cd2b1df1b9153f25.png

图中,身为左孩子的Y取代了X的位置,而X变成了自己的右孩子。此为右旋转。

47070609c38935839fd5066bb29740b6.png
c0d04185bf07786fdcf13b19d3606f4b.png
05c53e569f8836aedabfa8a70b5debbf.png

局面1:新结点(A)位于树根,没有父结点。

383f30a36a44002eae85a50a77ac74c4.png

(空心三角形代表结点下面的子树)

这种局面,直接让新结点变色为黑色,规则2得到满足。同时,黑色的根结点使得每条路径上的黑色结点数目都增加了1,所以并没有打破规则5。

df353c8b662e42785884beff69f7d205.png

局面2:新结点(B)的父结点是黑色。

这种局面,新插入的红色结点B并没有打破红黑树的规则,所以不需要做任何调整。

823bbb0361c23e32bf8c423eaa2877c0.png

局面3:新结点(D)的父结点和叔叔结点都是红色。

4d1737658b1ae3bdaea573c0775a9c28.png

这种局面,两个红色结点B和D连续,违反了规则4。因此我们先让结点B变为黑色:

d1ab893bebef4eb17b8558623f641ab8.png

这样一来,结点B所在路径凭空多了一个黑色结点,打破了规则5。因此我们让结点A变为红色:

01cc387da19e164027d615f1426b2d3c.png

这时候,结点A和C又成为了连续的红色结点,我们再让结点C变为黑色:

0226ad216bb07803e88c3fcfd4680fb5.png

经过上面的调整,这一局部重新符合了红黑树的规则。

局面4:新结点(D)的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的右孩子,父结点(B)是祖父结点的左孩子。

6c4ff419d55678fcfc73d517e508b6e6.png

我们以结点B为轴,做一次左旋转,使得新结点D成为父结点,原来的父结点B成为D的左孩子:

b7238ef9b4cec781761d650c2dd500d5.png

这样一来,进入了局面5。

局面5:新结点(D)的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的左孩子,父结点(B)是祖父结点的左孩子。

7f8ed6a5144aab14cc879edca6a695a5.png

我们以结点A为轴,做一次右旋转,使得结点B成为祖父结点,结点A成为结点B的右孩子:

aa734eb40112edd87dbfd4e2cbed9e34.png

接下来,我们让结点B变为黑色,结点A变为红色:

4962384ef58dffe855a762b5e171e8f7.png

经过上面的调整,这一局部重新符合了红黑树的规则。

以上就是红黑树插入操作所涉及的5种局面。

或许有人会问,如果局面4和局面5当中的父结点B是祖父结点A的右孩子该怎么办呢?

很简单,如果局面4中的父结点B是右孩子,则成为了局面5的镜像,原本的右旋操作改为左旋;如果局面5中的父结点B是右孩子,则成为了局面4的镜像,原本的左旋操作改为右旋。

175ca0d318ec092b9685ea121a0f1714.png
2c3bf57a004be7c128c13ecb588bfecb.png

给定下面这颗红黑树,新插入的结点是21:

d7ec55af9144f13acda34be2f8574980.png

显然,新结点21和它的父结点22是连续的红色结点,违背了规则4,我们应该如何调整呢?

让我们回顾一下刚才讲的5种局面,当前的情况符合局面3:

“新结点的父结点和叔叔结点都是红色。”

于是我们经过三次变色,22变为黑色,25变为红色,27变为黑色:

40f3d975d4e9bd7c3b4e24f6c80dcd02.png

经过上面的调整,以结点25为根的子树符合了红黑树规则,但结点25和结点17成为了连续的红色结点,违背规则4。

于是,我们把结点25看做一个新结点,正好符合局面5的镜像:

“新结点的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的右孩子,父结点是祖父结点的右孩子”

于是我们以根结点13为轴进行左旋转,使得结点17成为了新的根结点:

e6c1044bdaef794d79a180ec65ef0a3d.png

接下来,让结点17变为黑色,结点13变为红色:

bf3a12fd9872f1430ab6c5a30d3e25f0.png

如此一来,我们的红黑树变得重新符合规则。

654716c4e1084282294aed52fd54d0d9.png
74fe156fe9e0793604b4a791ae09dbf3.png
6268ab6c34fc157cdcb6ee5de8667ffc.png

作为一名程序员我们必须不断学习技术知识,更新自己的知识储备
对于一名程序员来说,技术知识方面是非常重要的,可以说是重中之重。要面试大厂,自己的知识储备一定要非常丰富,若缺胳膊少腿,别说在实际工作当中,光是面试这一关就过不了。对于技术方面,首先基础知识一定要扎实,包括自己方向的语言基础、计算机基础、算法以及编程等等。

结合自身的一个学习经历,总结了一套非常系统的复习包,包括思维脑图、Android基础知识、JAVA知识点汇总、Android扩展知识点、Android开源库源码分析、设计模式汇总、Gradle知识点汇总、常见面试算法题汇总等等。

01Android基础知识:

笔记里的知识点非常齐全,囊括了Activity、数据储存、屏幕适配、消息机制、线程异步、webview、进程、ipc、数据储存等大量知识点,每一个知识点都有非常详细的解析,这本万能宝典在手,不信还有搞不懂的面试题!

6b0c950c1f7a33fec07bb013a2fdf0a9.png

01JAVA知识点汇总:

笔记里的知识点非常齐全,囊括了JVM、static、并发、Java反射、Spring原理、微服务、异常处理、数据库、数据结构等大量知识点,每一个知识点都有非常详细的解析,这本万能宝典在手,不信还有搞不懂的面试题!

f342fb6ef57ff0a54b46ef39a8189d68.png

02 手撕架构技术篇

该篇内容囊括了以下专题的高频面试题、实战文档以及使用总结。

415008e022ed0b1b612554d7b73fb275.png

03 最新大厂面试专题

这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等

acabec4d9df8dc4844c5577ad5991229.png

04 实战电子书

关于实战,我想每一个做开发的都有话要说,对于小白而言,缺乏实战经验是通病,那么除了在实际工作过程当中,我们如何去更了解实战方面的内容呢?实际上,我们很有必要去看一些实战相关的电子书。目前,我手头上整理到的电子书还算比较全面,HTTP、自定义view、c++、MVP、Android源码设计模式、Android开发艺术探索、Java并发编程的艺术、Android基于Glide的二次封装、Android内存优化——常见内存泄露及优化方案、.Java编程思想 (第4版)等高级技术都囊括其中。

65e0cb104c3de074e6b7cc1e8637a379.png

05Android小白到Android工程师的系统学习视频

关于视频这块,我也是自己搜集了一些,都按照Android学习路线做了一个分类。按照Android学习路线一共有八个模块,其中视频都有对应,就是为了帮助大家系统的学习。接下来看一下导图和对应系统视频吧!!!

  • Android高级工程师进阶思维导图
3c64c1a27c19ca6d809bed923b01a26a.png
  • 对应导图的Android高级工程师进阶系统学习视频
d382e0234bca4f9b2391354c2403c46b.png

私信我【学习】加入我们的圈子领取资料和我们一起吧学习交流吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值