您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > JAVA

看了这么多篇红黑树文章,你理解了嘛?

时间:2019-09-23 11:02:46  来源:  作者:
整篇文章的思路是这样的,红黑树其实就是一种数据结构,设计它的目的就是为了高效地进行增删改查,所以我们文章的顺序也会按照这个思路来进行。我们先从二叉查找树逐渐引入到红黑树,然后再详细的讲解。你如果看过其他文章想必也一定清楚,红黑树比较麻烦,希望你有点耐心,认真理解每一张图再往下分析。

一、二叉查找树

在正式开始了解红黑树之前呢,我们先来看一下二叉查找树的概念,从浅入深,希望你不要着急,下面就是是一颗二叉查找树:

看了这么多篇红黑树文章,你理解了嘛?

 

从这张图我们会发现如下的规律:

(1)左子树上所有节点的值均小于或等于它的根结点的值。

(2)右子树上所有节点的值均大于或等于它的根结点的值。

如果我们想要查找一个数字11,过程是怎么样的呢?

看了这么多篇红黑树文章,你理解了嘛?

 

上面的过程已经很清晰了,在查找的时候,先与根节点比较,比根节点大则从右子树查找,比根节点小则从左子树查找,然后重复上面的过程,一直到找到我们需要的元素为止。

这个过程是查找操作,对于添加和删除呢?其实原理也是一样的,我们第一步就是找到我们需要插入的位置,然后把元素插入即可。这样看二叉查找树挺好的呀?别着急我们继续往下看这种情况。

如果我们在刚刚开始的时候还是以9为根节点,然后依次插入13、15、17、19。我们看会发生什么情况:

看了这么多篇红黑树文章,你理解了嘛?

 

好好地一棵树变成了这个鬼样子,成了“一边倒”了。这时候再去查找19呢?

看了这么多篇红黑树文章,你理解了嘛?

 

这效率也太低下了吧,一颗二叉查找树的优势完全丧失了。怎么办呢?既然上面的二叉查找树在插入的时候变成了“一条腿”,也就是丧失了平衡,那我们干脆做出一点改进,使用平衡二叉树吧。

二、平衡二叉树

下面就是一颗平衡二叉树。

看了这么多篇红黑树文章,你理解了嘛?

 

上面这颗二叉树就是平衡二叉树,也叫作AVL树。仔细分析你会发现如下特点:

(1)从任何一个节点出发,左右子树深度之差的绝对值不超过1。

(2)左右子树仍然为平衡二叉树。

现在我们再往里插入一个元素4,这时候会发生什么呢?

看了这么多篇红黑树文章,你理解了嘛?

 

从图中我们可以看到,插入了4之后破坏了平衡,怎么办呢?既然破坏了平衡,那就想办法纠正过来。

看了这么多篇红黑树文章,你理解了嘛?

 

我们发现经过调整之后,我们二叉树就重新回到了平衡。对于其他插入的情况,大家可以自己私下试一遍,最终你会发现一个结论,那就是平衡二叉树在插入时最多只需要两次旋转就会重新恢复平衡。

从上面这个过程我们会发现,平衡二叉树真的很不错,在查找时既有着二叉查找树的优越性,在插入时还能通过调整继续保持着。那么为什么还要使用到红黑树呢?我觉得可以从以下两个方面来考虑:

(1)删除:对于平衡二叉树来说,在最坏情况下,需要维护从被删节点到根节点这条路径上所有节点的平衡性,旋转的量级是O(logN)。但是红黑树就不一样了,最多只需3次旋转就会重新平衡,旋转的量级是O(1)。

(2)保持平衡:平衡二叉树高度平衡,这也就意味着在大量插入和删除节点的场景下,平衡二叉树为了保持平衡需要调整的频率会更高。

注意:在大量查找的情况下,平衡二叉树的效率更高,也是首要选择。在大量增删的情况下,红黑树是首选。

鉴于以上原因,因此我们才使用到了红黑树这种更好的结构。上面提了这么多次红黑树,相信你已经迫不及待的想要认识一下了。下面就正式拉开红黑树的序幕。

三、红黑树

红黑树听名字就知道,里面涉及到两种颜色:红色和黑色。我们直接来看一下:

看了这么多篇红黑树文章,你理解了嘛?

 

上面这张图就是红黑树,你会发现他有如下特征(下面的特征最好看一个特征重新看一遍红黑树):

(1)每个节点只有两种颜色:红色和黑色。

(2)根节点是黑色的。

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

(4)从根节点到叶子节点,不会出现两个连续的红色节点。

(5)从任何一个节点出发,到叶子节点,这条路径上都有相同数目的黑色节点。

这五条就是红黑树的特征,你每看一个特征最好重新看一遍图,这样可以加深理解。这五条特征看起来真的很复杂,不过正是由于这些复杂的特征才保证了红黑树的良好特性。如何保证的呢?我们从增删改查四个角度来一个一个分析一下:

1、查询节点

查询节点是最简单的一个,他的查找过程和二叉查找树一样,查找元素比当前节点大,就从右子树继续查找比较,查找元素比当前节点小,就从左子树继续查找比较。查找过程就不再赘述了。

2、插入节点

插入节点是最麻烦的一个,它分为三种情况。我们一种一种看,这样比较有条理性。

第一种情况:新节点没有父节点

没有父节点只有一种情况,就是插入的节点是整棵树第一个节点,也就是根节点,为此我们只需要把插入节点涂成黑色就OK了。这也就保证了性质2:根节点是黑色的。

第二种情况:新节点的父节点是黑色

为此我们举一个例子,比如说上面的红黑树中,我们插入节点14。来看一下会发生什么情况?

看了这么多篇红黑树文章,你理解了嘛?

 

这种情况我们发现新插入节点14的父节点就是黑色的。现在为了保证红黑树的性质,我们对照每个特性来检查一遍。只要有一条不满足,我们都需要调整。我们重新对照之后会发现每一条都符合。此时不需要调整。

第三种情况:新节点的父亲节点为红色

我们还是举个例子,比如我们在最开始的红黑树基础之上插入节点21,此时会发生什么情况呢?

看了这么多篇红黑树文章,你理解了嘛?

 

此时还是老规矩,对照着红黑树的5个特征一个一个来看,只要是违反了一条就需要做出调整。我们来看一下:

(1)每个节点只有两种颜色:红色和黑色。这一条满足。

(2)根节点是黑色的。这一条也满足。

(3)每个叶子节点(NIL)都是黑色的空节点。这一条满足。

(4)从根节点到叶子节点,不会出现两个连续的红色节点。这一条发现不满足。

就是上面这一条规则没有满足,所以我们此时需要调整?问题来了如何调整呢?因为直接看父节点没办法实现,所以还需要观察另外的节点,也就是新节点的叔叔节点。根据叔叔节点的颜色来调整。调整的方式有两种:变色和旋转。

(1)叔叔节点是红色:

此时插入的节点是21,但是叔叔节点是27,更好是红色。我们直接来看调整的步骤:

第一步:把新节点21的父节点22变成黑色。

看了这么多篇红黑树文章,你理解了嘛?

 

此时重新看一下是否满足红黑树的五条特征了没,一条一条发现,第五条没有满足,也就是从任何一个节点出发,到叶子节点,这条路径上没有相同数目的黑色节点。比如从25出发。这时候怎么办呢?那就继续调整。

第二步:把22的父节点25变成红色

看了这么多篇红黑树文章,你理解了嘛?

 

这时候还是老规矩,不要嫌弃麻烦,因为只有经历了一步又一步的麻烦之后,你才能牢记那5条规则特征。我们对照之后会发现节点25和节点27是两个连续的红色节点,这时候又破坏了规则4。怎么办呢?那就继续调整就OK了。

难道这时候还要继续往上调整吗?如果你这样做就错了,因为不断地往上调整最后就会把根节点变成了红色,会走进死胡同。我们往下走。

第三步:把节点27变成黑色

看了这么多篇红黑树文章,你理解了嘛?

 

来吧,继续重新审查那5条规则特征。很明显节点17和节点25是两个连续的红色,又破坏了。是不是心太累了,调整了这么久,还是没有保证那5条规则,感觉是不是还没有平衡二叉树好。如果你现在有这种感觉,我只能说,希望你继续坚持下去,胜利就在眼前。

第四步:把节点17和节点18都变成黑色节点

看了这么多篇红黑树文章,你理解了嘛?

 

来来来,现在你再对照一下那5条规则,是不是完全保证了。写到这真的是太累了,和你读这篇文章的感觉一样一样的,不过这种情况也只是插入情况中的一种。继续往下看:

(1)叔叔节点是黑色:

这种情况下又分了两种情况:

第一种情况:新插入节点为父节点的左孩子

看了这么多篇红黑树文章,你理解了嘛?

 

第二种情况:新插入节点为父节点的右孩子

看了这么多篇红黑树文章,你理解了嘛?

 

按照第一遍的思路,我们对这两种情况执行同样的操作,最终也能保证红黑树的5条特征。

到了这一步,插入操作的所有情况就讲解完毕。另外关于左旋和右旋的知识我在这里不再说明了,因为你看到了红黑树这个程度,相信也一定看过平衡二叉树。左旋右旋哪几种情况,都会有介绍到。

3、删除节点

红黑树的删除说实话更加的复杂,如果你看过算法导论的话应该能明白一点,我们在这里也进行一个大概的讲解。

删除大致分了三种情况,

(1)第一种情况:要删除的节点有零个子节点

这种情况下最简单,也就是删除的是根节点或者是叶子节点(这里的叶子节点都是指非NULL的叶子节点),根节点直接删除即可。如果叶子节点是红色的,也可以直接删除,如果叶子节点是黑色的,那么就需要进行调整,调整的步骤和插入时调整的步骤一样。

(2)第二种情况:要删除的节点有一个子节点

这时候。把子节点的值替换掉要删除的节点的值。

看了这么多篇红黑树文章,你理解了嘛?

 

现在我们的5把11替换掉之后,又回到了第一种情况。如果节点5是红色的,可以直接删除,如果节点5是黑色的,那么就需要进行调整,此时的节点5就是叶子节点。调整的步骤和插入时调整的步骤一样。

(3)第三种情况:要删除的节点有两个子节点

现在删除的节点有两个子节点,同样的我们可以执行第二种情况的操作,

看了这么多篇红黑树文章,你理解了嘛?

 

若节点13之前是叶子节点,那就和第一种情况一样了,如果节点13是红色的,可以直接删除,如果节点13是黑色的,那么就需要进行调整,此时的节点13就是叶子节点。调整的步骤和插入时调整的步骤一样。

若节点13之前还有子节点,那就和第二种情况一样了。那就继续替换和判断。

以上呢就是删除的情况,最后一种情况是修改,这种情况是查找和插入的结合体,也就是先找到要修改的元素,修改完值之后,继续进行调整即可。

现在还有最后一个问题了,都说红黑树很重要,为什么重要呢?我们来看一下使用场景。

四、使用场景

红黑树的应用真的是太多了,比如说JAVA中的HashMap和TreeMap。还有就是linux也经常使用到。这种数据结构在面试的时候是一个常问问题,希望大家能够明白和理解。如何用java手撕红黑树,在后续文章中我会添加。如有问题还请批评指正。



Tags:红黑树   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
C++ STL之std::map:红黑树的魔法与性能测试
最近在使用C++写代码,也是刚接触C++,恰巧碰到一个需要使用map的地方,不知道其查找元素的性能怎么样,所以研究了下,做个记录,目前从x86平台测试map查找一个元素大概需要2us,这里你需...【详细内容】
2023-11-23  Search: 红黑树  点击:(209)  评论:(0)  加入收藏
一文搞懂二叉搜索树、B树、B+树、AVL树、红黑树
我们假设B+树一个节点可以有100个关键字,那么3层的B树可以容纳大概1000000多个关键字(100+101100+101101*100)。而红黑树要存储这么多至少要20层。所以使用B树相对于红黑树和A...【详细内容】
2023-08-29  Search: 红黑树  点击:(411)  评论:(0)  加入收藏
红黑树插入调整方案
红黑树插入有五种情况,每种情况对应着不同的调整方法:一、 新结点(A)位于树根,没有父结点。直接让新结点变色为黑色,规则2得到满足。同时,黑色的根结点使得每条路径上的黑色结点数...【详细内容】
2023-03-31  Search: 红黑树  点击:(239)  评论:(0)  加入收藏
面试让我手写红黑树
作者:小傅哥 博客:https://bugstack.cn沉淀、分享、成长,让自己和他人都能有所收获!一、前言:挂在树上!不知道你经历过HashMap的夺命连环问!为啥,面试官那么喜欢让你聊聊 HashMap?因...【详细内容】
2022-10-10  Search: 红黑树  点击:(221)  评论:(0)  加入收藏
比红黑树更快的跳表到底是什么数据结构?如何实现?
前言在头条创作了一个月左右的时间,收获了50+粉丝,很是开心,我会把数据结构与算法的文章更新到底,第一次看我文章的同仁如果觉得不错的话就关注一下我哦,你的支持就是我创作的动...【详细内容】
2022-10-10  Search: 红黑树  点击:(318)  评论:(0)  加入收藏
红黑树以及JAVA实现
前言红黑树是一种特殊的B树是B树种2-3-4树的一种特殊实现,红黑树保证了每个节点只会有两个子节点,通过对每个节点进行染色,然后通过不同颜色的节点组合来分别代表2-3-4的2节点...【详细内容】
2022-08-15  Search: 红黑树  点击:(315)  评论:(0)  加入收藏
数据结构 --- 红黑树
和AVL树一样,红黑树也是自平衡二叉搜索树。红黑树同样解决了在特定情况下二叉搜索树会退化成链表的问题。但是红黑树又不像AVL树那样高度平衡,这就让红黑树在插入删除频繁的场...【详细内容】
2022-06-16  Search: 红黑树  点击:(270)  评论:(0)  加入收藏
红黑树底层原理及Linux内核红黑树算法深度研究
1. 红黑树1.1 红黑树概述红黑树和我们以前学过的AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。不过自从红黑树出来后,AVL...【详细内容】
2021-06-24  Search: 红黑树  点击:(407)  评论:(0)  加入收藏
一文看懂 HashMap 中的红黑树实现原理
前言本文咱们了解一下红黑树的设计,相比 jdk1.7 的 HashMap 而言,jdk1.8 最重要的就是引入了红黑树的设计,当冲突的链表长度超过 8 个的时候,链表结构就会转为红黑树结构。01、...【详细内容】
2021-01-18  Search: 红黑树  点击:(356)  评论:(0)  加入收藏
看了两天HashMap源码,终于把红黑树插入平衡规则搞懂了
絮叨学校短学期刚结束了,离学校开学还有很多天,一直呆在寝室玩游戏岂不是浪费了大好时光,于是心血来潮想看看HashMap的源码。虽然我没有经历过面试,但是java程序员都知道,HashMap...【详细内容】
2020-09-27  Search: 红黑树  点击:(285)  评论:(0)  加入收藏
▌简易百科推荐
Java 8 内存管理原理解析及内存故障排查实践
本文介绍Java8虚拟机的内存区域划分、内存垃圾回收工作原理解析、虚拟机内存分配配置,以及各垃圾收集器优缺点及场景应用、实践内存故障场景排查诊断,方便读者面临内存故障时...【详细内容】
2024-03-20  vivo互联网技术    Tags:Java 8   点击:(17)  评论:(0)  加入收藏
如何编写高性能的Java代码
作者 | 波哥审校 | 重楼在当今软件开发领域,编写高性能的Java代码是至关重要的。Java作为一种流行的编程语言,拥有强大的生态系统和丰富的工具链,但是要写出性能优异的Java代码...【详细内容】
2024-03-20    51CTO  Tags:Java代码   点击:(25)  评论:(0)  加入收藏
在Java应用程序中释放峰值性能:配置文件引导优化(PGO)概述
译者 | 李睿审校 | 重楼在Java开发领域,优化应用程序的性能是开发人员的持续追求。配置文件引导优化(Profile-Guided Optimization,PGO)是一种功能强大的技术,能够显著地提高Ja...【详细内容】
2024-03-18    51CTO  Tags:Java   点击:(29)  评论:(0)  加入收藏
Java生产环境下性能监控与调优详解
堆是 JVM 内存中最大的一块内存空间,该内存被所有线程共享,几乎所有对象和数组都被分配到了堆内存中。堆被划分为新生代和老年代,新生代又被进一步划分为 Eden 和 Survivor 区,...【详细内容】
2024-02-04  大雷家吃饭    Tags:Java   点击:(60)  评论:(0)  加入收藏
在项目中如何避免和解决Java内存泄漏问题
在Java中,内存泄漏通常指的是程序中存在一些不再使用的对象或数据结构仍然保持对内存的引用,从而导致这些对象无法被垃圾回收器回收,最终导致内存占用不断增加,进而影响程序的性...【详细内容】
2024-02-01  编程技术汇  今日头条  Tags:Java   点击:(75)  评论:(0)  加入收藏
Java中的缓存技术及其使用场景
Java中的缓存技术是一种优化手段,用于提高应用程序的性能和响应速度。缓存技术通过将计算结果或者经常访问的数据存储在快速访问的存储介质中,以便下次需要时可以更快地获取。...【详细内容】
2024-01-30  编程技术汇    Tags:Java   点击:(75)  评论:(0)  加入收藏
JDK17 与 JDK11 特性差异浅谈
从 JDK11 到 JDK17 ,Java 的发展经历了一系列重要的里程碑。其中最重要的是 JDK17 的发布,这是一个长期支持(LTS)版本,它将获得长期的更新和支持,有助于保持程序的稳定性和可靠性...【详细内容】
2024-01-26  政采云技术  51CTO  Tags:JDK17   点击:(95)  评论:(0)  加入收藏
Java并发编程高阶技术
随着计算机硬件的发展,多核处理器的普及和内存容量的增加,利用多线程实现异步并发成为提升程序性能的重要途径。在Java中,多线程的使用能够更好地发挥硬件资源,提高程序的响应...【详细内容】
2024-01-19  大雷家吃饭    Tags:Java   点击:(111)  评论:(0)  加入收藏
这篇文章彻底让你了解Java与RPA
前段时间更新系统的时候,发现多了一个名为Power Automate的应用,打开了解后发现是一个自动化应用,根据其描述,可以自动执行所有日常任务,说的还是比较夸张,简单用了下,对于office、...【详细内容】
2024-01-17  Java技术指北  微信公众号  Tags:Java   点击:(102)  评论:(0)  加入收藏
Java 在 2023 年仍然流行的 25 个原因
译者 | 刘汪洋审校 | 重楼学习 Java 的过程中,我意识到在 90 年代末 OOP 正值鼎盛时期,Java 作为能够真正实现这些概念的语言显得尤为突出(尽管我此前学过 C++,但相比 Java 影响...【详细内容】
2024-01-10  刘汪洋  51CTO  Tags:Java   点击:(81)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条