说说红黑树——不谈操作,只讲理解

一、前言

??这几天想学一学红黑树这种数据结构,于是上网找了很多篇博客,初看吓了一跳,红黑树竟然如此复杂。连续看了几篇博客后,算是对红黑树有了一些了解,但是它的原理却并不是特别理解。网上的博客,千篇一律的都是在叙述红黑树的操作,如何插入节点、删除节点,旋转、变色等,只关注如何正确构建一棵红黑树,但是却很少提及为什么这么做。这篇博客我就来记录一些我所知道的红黑树中比较重要的东西,以及谈一谈我的理解。

??我不会描述红黑树的具体实现,因为阅读红黑树具体实现的过程中,我发现这真的不是很重要,没有太大的意义(这绝对不是自我安慰⊙﹏⊙∥),真正重要的是红黑树的思想。如果想要了解红黑树的具体实现,建议阅读这篇文章:https://mp.weixin.qq.com/s/hGHJonK999TAVJakPDNAkg

二、正文

? 2.1 二叉搜索树和平衡二叉树

??在谈二叉红黑树之前,先来说一说二叉搜索树以及平衡二叉树,因为平衡二叉树是为了弥补二叉搜索树而发明出来的,而红黑树又是为了弥补平衡二叉树。

?(1)二叉搜索树

??二叉搜索树比较简单,它是一棵二叉树,而且满足这样一个性质:对于树上的每一个节点,它左子树上的节点的值都比它小,而右子树上的节点的值都比它大。如下,就是一棵二叉搜索树:

??当我们需要往一棵二叉搜索树中插入节点时,只需要从根节点开始,依次比较,若比根节点小,则向左走,继续和左子节点比较,反之继续和右子节点比较,以此类推。这样的操作其实就和二分差不多,在节点值分布均匀的情况下,也就是树的结构如上所示时,查找的时间复杂度为O(logN),因为二叉搜索树的查询完全复杂度依赖于树的深度。所以,它有一个很大的缺陷,就是可能出现如下情况:

??我们每次插入的节点都比最小值要小,于是最终所有的节点就连成了一条链,此时深度为N,查找的时间复杂度就是O(N)了。为了解决这个问题,于是又有了平衡二叉树。关于二叉搜索树,可以参考这个博客:https://www.jianshu.com/p/ff4b93b088eb

?(2)平衡二叉树

??平衡二叉树也是一棵二叉搜索树,但是它还有一个性质,就是这棵树上的每一个节点,其左子树和右子树的高度差都不超过一。比如图一中的二叉树,它就时一棵平衡二叉树,而下面这张图中的树就不是平衡二叉树,因为节点9和节点5都不平衡,它们的左右子树的高度差都是2

??当发生不平衡的情况时,可以通过左旋和右旋的方式,在不改变二叉搜索树的性质的前提下,将树调整为平衡状态,这就是平衡二叉树。对于左旋和右旋的具体实现,我这里就不描述了,想要了解可以参考这篇博客:https://www.jianshu.com/p/655d83f9ba7b

? 2.2 有了二叉搜索树和平衡二叉树,为什么还要红黑树

??这个问题是一个面试题,下面我就来简单叙述一下。首先,二叉搜索树在极端情况下会变成一个链表,从而导致查询的时间复杂度大大提高,变成线性复杂度,而平衡二叉树正是为了解决这个问题才被发明出来。但是,平衡二叉树也有一定的局限。对于平衡二叉树来说,每个节点的子树的高度差不能超过1,一旦出现违反的情况,就需要进行左旋或者右旋操作,从而调整二叉树的高度。但是,在插入和删除节点的过程中,平衡度超过1是经常发生的事情,这也就导致了调整操作频繁地发生,从而提高时间复杂度。也就是说,这种追求绝对平衡的行为,并不是一个好的做法。

??红黑树的出现正是为了解决平衡二叉树的问题,它是平衡二叉树的变形,或者说升级。红黑树并不追求绝对的平衡,它实现的是近似的平衡,这样破坏规则导致需要调整的情况就会大大减少,而且每次也只需要少量的调整即可恢复。也就是说,他在平衡和效率之间做了一个折中。但是统计发现,这种折中对查找的效率并没有多大的降低,这也就导致了红黑树在大多数情况下要优于平衡二叉树。而红黑树的这种折中,依靠的就是它五条性质,或者说五条约束来实现。

? 2.3 红黑树的五大性质

??这里先放出红黑树的五大性质:

  1. 树中的所有节点,要么是红色,要么是黑色;
  2. 树的根节点是黑色;
  3. 树中的叶子节点是黑色;(注意:这里的叶子节点不是指没有子节点的节点,而是指的空节点,比如某个节点没有左子节点,那这个不存在的左子节点其实就是这里说的叶子节点)
  4. 红色节点的子节点一定是黑色,也就是说没有两个连在一起的红色节点;
  5. 每个节点到任意一个叶子节点,经过的黑色节点数量是相等的;

??这五条性质单独分开来看都很好理解,但是放在一起就有点迷惑了,为什么是这五条性质,它们之间有什么关系?关系肯定是有的,发明红黑树的专家,经过大量的数学推导,理论验证,才组合出这五条性质,它们相辅相成,共同维护了红黑树的结构。就像机器人三大准则一样,相辅相成,完全地约束了机器人的行为。这里就来简单描述几条红黑树的定理,它们都是由上述结论推导而来。

? 2.4 红黑树的定理

?(1)红黑树从根节点到叶子节点的最长路径,不会大于最短路径的两倍

??这条定理是怎么来的呢?它是通过上面的定理推导而来。我们看上述性质5可知,从根节点到任意一个叶子节点,经过的黑色节点数目是相同的。而性质4又规定,不能有两个红色节点连在一起。于是我们这样考虑,假设从根节点到每个叶子节点,都是经过3个黑色节点,那么怎样才能让路径尽可能长?答案当然是尽量在黑色节点中插入红色节点,用红色节点充数。但是由于性质4,所以红色节点不能多放。于是,理论上的最长路径,一定是一个黑节点,连着一个红节点,再连着一个黑节点,以此类推。我们之前假设每条路径都是3个黑节点,再加上性质2说根节点一定是黑色,所以从根节点到子节点最多只能有6个节点,三黑三红交叉连接。那理论上的最短路径又是如何?当然是不包含任何一个红色节点,也就是只有3个黑节点。也就是说,理论上,最长路径,最多是最短路径的两倍。这个结论就限制了红黑树的最大平衡差,也就保证了不会出现图二这种情况。

?(2)一棵含有n个节点的红黑树的高度至多为2log(n+1)

??这个结论是经过一系列数学推导得出的,比较复杂,我也没有仔细研究过,想要了解的可以看看这篇博客:https://www.cnblogs.com/skywang12345/p/3245399.html#a2

??从这个结论可以看出什么?红黑树也是一个二叉搜索树,而二叉搜索树的查找次数取决于树的深度。此结论说明红黑树的高度至多为2log(n+1),也就是说红黑树的查找效率也是O(logn)级别的,和平衡二叉树近似,再加上红黑树的调整平衡的次数相对较少,所以总体来说,红黑树要优于平衡二叉树。

三、总结

??最后我忍不住吐槽一下,我看了大量红黑树的讲解博客,都是千篇一律的在描述如何操作构建一棵红黑树,如何操作能够不违反红黑树的这五条性质,一旦讲完操作就戛然而止。在学习红黑树时,我硬着头皮把红黑树的操作看完,才发现这些操作根本没有太大的意义,它们只不过是列举操作红黑树的各种情况,告诉你什么时候应该怎么做而已,而你只能背下这些操作,但是完全不能理解这些操作有什么意义,只知道它们唯一的作用就是维持这五大性质。仿佛将红黑树的操作实现强行记下,写出代码,就是学会了红黑树,理解了红黑树。可是实际上,这五条性质只是结论,只是他人研究的最终产物罢了,而红黑树仅仅是在使用这些结论。如果只是学会了红黑树的实现方式,仅仅只是在使用这些结论,和调API有什么区别。但是,网上的博客都是千篇一律,偏偏标题取得是一个比一个厉害,什么《学会红黑树这一篇就够了》,《十分钟彻底理解红黑树》,《看完这篇博客,再也不怕面试管问红黑树了》......这些标题的博客数不胜数,但是内容却都是在介绍操作,极少叙述思想。一想到我花了大量时间,最后发现自己看的都是些意义不大的实现细节,就感觉对不起自己。

??我个人认为,学习算法和数据结构,真正重要的是理解它的思想,而不是如何做。说句实话,如果不是做算法相关的工作,工作中真的需要我们自己写红黑树吗?可以说基本上不可能用到。当然,不是说研究具体实现是一种错误的行为,研究算法和数据结构的实现能够锻炼自己的编码能力,是有好处的。但是大部分人是为了学习数据结构本身,如果只学会了写代码,不知道原理,那就有点本末倒置了,而且很快就会忘记。

四、参考

原文地址:https://www.cnblogs.com/tuyang1129/p/12556519.html

时间: 2024-10-12 02:24:13

说说红黑树——不谈操作,只讲理解的相关文章

红黑树(3) - 删除操作

在本系列的前面两篇文章中,已经介绍了红黑树以及其插入操作.具体可参考下面两个链接: 红黑树(1) - 介绍 红黑树(2) - 插入操作 1.删除操作介绍 类似于插入操作,红黑树进行删除节点时,也使用重新着色以及旋转这两种方式,来维护它的属性.在插入操作中,我们主要是依靠检测叔节点的颜色来决定哪种场景.在删除操作中,我们使用检测兄弟的颜色,来决定是哪种场景. 在插入操作中,最常见的违反红黑树属性的一种情况是存在两个连续的红色节点.而在删除操作中,常见的情况是,当删除节点是黑色时,会影响从根节点到叶

红黑树(2) - 插入操作

1.插入介绍 首先以二叉排序树的方法增加节点并标记它为红色.(为何不是红色?因为如果设为黑色,就会导致根到叶子的所有路径中,有一条路径上会多出一个额外的黑节点,这个是很难调整的).但是,设为红色节点后,可能会导致出现两个连续红色节点的冲突,则可以通过重新着色和旋转来调整.具体的调整操作取决于其他临近节点的颜色. 下面分析一下插入新节点后可能对红黑树性质产生的影响: 性质1-节点是红色或黑色.和性质3-所有叶子都是黑色.这两条总是可以维持不变. 性质4-每个红色节点的两个子节点都是黑色.只在增加红

红黑树的删除操作详解

注:本文转载自博客园,博主原址:http://www.cnblogs.com/tongy0/p/5460623.html,感谢博主帮我弄清楚了红黑树删除操作,转载做收藏用. 红黑树的删除操作 1:节点命名约定 D表示要被删除的节点.即:取 Delete 的首字母: P 表示父节点.即:取 Parent 的首字母: S表示兄弟姐妹节点.即:取 Sibling的首字母: U表示叔伯节点.即:取Uncle的首字母: G表示祖父节点.即:取 Grandfather的首字母: L表示左树.即:取Left的

红黑树的插入操作

1 package Tree; 2 3 import org.junit.Test; 4 5 class RedBlackTreeNode { 6 7 int key = 0; 8 RedBlackTreeNode left = null; 9 RedBlackTreeNode right = null; 10 RedBlackTreeNode parent = null; 11 // 色域,0表示黑色,1表示红色 12 int color; 13 14 public RedBlackTreeN

浅谈算法和数据结构: 七 二叉查找树 八 平衡查找树之2-3树 九 平衡查找树之红黑树 十 平衡查找树之B树

http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html 前文介绍了符号表的两种实现,无序链表和有序数组,无序链表在插入的时候具有较高的灵活性,而有序数组在查找时具有较高的效率,本文介绍的二叉查找树(Binary Search Tree,BST)这一数据结构综合了以上两种数据结构的优点. 二叉查找树具有很高的灵活性,对其优化可以生成平衡二叉树,红黑树等高效的查找和插入数据结构,后文会一一介绍. 一 定义 二叉查找树(B

浅谈算法和数据结构: 九 平衡查找树之红黑树

原文:浅谈算法和数据结构: 九 平衡查找树之红黑树 前面一篇文章介绍了2-3查找树,可以看到,2-3查找树能保证在插入元素之后能保持树的平衡状态,最坏情况下即所有的子节点都是2-node,树的高度为lgN,从而保证了最坏情况下的时间复杂度.但是2-3树实现起来比较复杂,本文介绍一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree) 定义 红黑树的主要是像是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息.红黑树中将节点之间的链接分为两种不同类型,

图解集合7:红黑树概念、红黑树的插入及旋转操作详细解读

原文地址http://www.cnblogs.com/xrq730/p/6867924.html,转载请注明出处,谢谢! 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储角度考虑,这两种数据结构是非常优秀的.另外,LinkedHashMap还额外地保证了Map的遍历顺序可以与put顺序一致,解决了HashMap本身无序的问题. 尽管如此,HashMap与LinkedHashMap还是有自己

红黑树一:从二叉树、2-3树到红黑树,一步步讲解红黑树的来源

目录 1 引言 2 从二叉查找树到红黑树的演变 2.1 二叉查找树 2.2 平衡二叉查找树 2.3 2-3树 2.4 红黑树 1 引言 RB-Tree,即红黑树,它的定义如下: 这是一颗二叉树,且每个节点要么是红色.要么是黑色 根节点是黑色 叶子节点也是黑色的,且叶子节点不存储数据,即叶子节点是nil空节点 不能出现连续的红色节点,即相邻的红色节点必须被黑色节点隔开 任何一个节点到达其任意一个叶子节点均包含相同数目的黑色节点 单看上面的定义,大家肯定跟我一样一头雾水,别急,下面我们从最简单的二叉

红黑树上的连接操作

a)①对于插入调整红黑树性质函数,注意到只有case1才会增加黑高,引用书中的图13-5所示 不管是a图还是b图,结点C从左图到右图黑高增加了1.其他结点黑高均无变化.具体13-5和13-6图所有结点黑高可以 参考13.3-3题目答案. ②对于删除调整红黑树性质函数,可以使用13.3-3类似的方法计算其黑高变化,结果就是case2的B结点减少1,case4结点D增加1,结点B减少1.(请参考图13-7)其他case和结点均无变化. ③对于删除函数如果是第3种情况,需要找到删除结点的后继,那么我们