数据结构——红黑树

目录

1. 引言

2. 红黑树的简单介绍

3. 红黑规则

4. 红黑树中默认插入节点是什么颜色效率更高?

5. 红黑树中插入节点的规则


上期帖子我讲述了二叉树的基本原理和相关知识点,这期我来讲述一个新的更加重要,非常重要的知识点,它就是红黑树。

1. 引言

大家都知道,HashMap的底层原理是面试官经常会问到的一个问题,那么大家知道在JDK1.8之后,HashMap 的底层是有什么改变吗?

在JDK1.8之前,HashMap底层是由数组+链表组成的。

在JDK1.8之后,HashMap底层是由数组+链表+红黑树构成的。添加了红黑树这种数据结构,优化了 HashMap,提高了数据的检索效率。这里只作简单介绍,如果各位想要深入了解 HashMap 的底层原理,可以去看我的另一篇文章

HashMap 底层源码深度解读_程序猿ZhangSir的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_70325779/article/details/132015542?spm=1001.2014.3001.5501

2. 红黑树的简单介绍

第一:红黑树它本身也是一个自平衡的二叉搜索树,但不是高度平衡的,和平衡二叉树略有区别,是一种特殊的二叉搜索树,在原本的二叉树节点的基础上,多了一个存储改节点颜色的数据。 

第二:1972年时被称为平衡二叉B树,在1978年改名为红黑树。上期帖子我讲述了平衡二叉树,想必各位也知道,平衡二叉树需要经常的进行旋转,这样会非常浪费资源和时间。因此,在平衡二叉树的基础上对它做了进一步的优化,就得到了如今的红黑树。

第三:红黑树必须满足特有的红黑规则

3. 红黑规则

相信说到了这里,一定有很多人好奇,这个红黑规则到底是什么呢?接下来就让我给你一一道来。

红黑树规则一定有以下五点,满足所有以下五点,即可被称为红黑树。

(1)每个节点要么是红色,要么是黑色。

(2)根节点必须是黑色,插入效率更高,后面会说到

(3)如果一个节点没有子节点或者父节点,则该节点相应的指针属性为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的。

(4)如果某一个节点是红色的,那么它的子节点必须是黑色的(不能出现两个红色节点相连的情况)。

(5)对每一个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。

如下图,就是一个简单的红黑树:

可以看到,根节点13即为黑色,所有叶子节点Nil也为黑色。

有一点要注意,虽然不能出现两个红色节点相连的情况,但是允许出现两个黑色节点相连。

还有一点也要注意,“简单路径” 就是指从根节点向下寻找,不可以回头;叶子节点就是指一个结点最下面的那一层,即Nil。

此外,我们都知道,二叉树的每个节点中,既保存了父结点的地址,左子节点的地址,右子节点的地址,又保存了自身数据。

但在红黑树中,每个节点除了保存上述四个数据之外,还要多一个位置来保存该节点的颜色。

如下图所示:

说完红黑树的基本概念,我们再来了解一下红黑树添加节点的规则。

4. 红黑树中默认插入节点是什么颜色效率更高?

这里要记住,红黑树中,添加的节点默认颜色均为红色,因为这样效率高。

可能有些小伙伴就会提出疑问了,为什么默认添加红色效率高呢?这里我举一个例子你就明白了。

假设有以下三个节点,20,18,23。

 现在将它们插入到红黑树中

 第一种情况,假设添加的节点默认颜色为黑色

1. 添加节点20时,因为根节点要求黑色,所以不需要改变颜色,添加20后得到的结果如下:

2. 添加节点18时,根据红黑规则,节点18应为红色,添加后如下所示:

 

3. 同理,添加节点23时,根据红黑规则,节点23应为红色,添加后如下所示:

总结上述三步,我们发现,节点18和节点23都修改了颜色,需要改变两次。

那我们再来看第二种情况,假设添加的节点默认颜色均为红色,会是什么情况呢?

我们来演示一遍,

1. 先添加节点20,因为根节点要求黑色,而现在默认为红色,所以需要进行修改

添加后结果如下:

2. 再添加节点18,默认为红色,添加之后如下,发现没有违反红黑规则,所以不需要进行修改

 3. 同理,再添加节点23,默认为红色,添加之后如下,发现没有违反红黑规则,所以不需要进行修改

总结上述三步,我们发现,若默认插入节点颜色为黑色,需要修改两次;若插入节点默认为红色,需要修改一次,所以默认红色时效率更高。感兴趣的小伙伴可以再换一个红黑树试一下,你会发现永远都是默认红色时,插入效率最高。

5. 红黑树中插入节点的规则

其实,除了添加节点默认为红色之外,还有一些别的规则我们需要注意,如下图所示:

OK,我们来试着做一道题,感受一下上述图中的插入规则,看如下图片,将图片中的各个节点插入到红黑树中,我们来试着做一下吧!

 

 第一步:先插入节点20,因为默认为红色,20为第一个节点,所以修改颜色为红色,如下:

 第二步:插入节点18,18与20作比较,比20小,插入到20的左边作为左子节点,不需要修改颜色,插入后如下所示:

 第三步:插入节点23,23与20作比较,比20大,插入到20的右边作为右子节点,不需要修改颜色,插入后结果如下所示:

 第四步:插入节点22,22与20作比较,比20大,插入到20的右边,再与23作比较,插入到23的左边,默认为红色,插入后为如下

 可以看出,已经违反了红黑规则,所以需要做出修改,我们看上述插入规则,非根,父节点红色,叔叔节点红色,所以进行四步操作;

(1)将父设为黑色,将叔叔设为黑色。得到如下

(2)将祖父设为红色。得到如下

(3)若祖父为根节点,再将根变为黑色。

 

(4)如果祖父为非根,将祖父设为当前节点在进行其他判断。此时判断,发现已经满足了红黑树规则,所以完成了插入操作。

经过一系列操作之后,得到的结果如下:

第五步:插入节点17,先判断,应插入在18的左侧。我们可以看到,若插入的节点非根且父节点为黑色,则不需要任何操作。插入后如下图所示:

 第六步:插入节点24,经判断应插入在23的右侧。可以看到,若插入的节点非根且父节点为黑色,则不需要任何操作。

第七步:插入节点19,经判断应插入在18的右侧。可以看到,若插入的节点非根且父节点为黑色,则不需要任何操作。

第六第七步一并操作,得到的结果如下:

OK,到这里上面7个数据就全部插入完成了,各位是不是觉得也不过如此啊,别急,还没有到难点的地方。下面我再做补充,假设我要在上述红黑树中再插入节点15和节点14,该怎么做呢?

我们来试试看

先插入15,进行判断,应该在17的左侧,插入后得到结果如下:

 发现违反了红黑规则,我们对其进行调整,可以看到,节点15的父节点17为红色,叔叔节点19也为红色,我们还要进行上面的四步操作:

(1)将父设为黑色,将叔叔设为黑色。得到如下

(2)将祖父设为红色。得到如下

(3)若祖父为根节点,再将根变为黑色。这里祖父18不为根节点,无需变色。

(4)如果祖父为非根,将祖父设为当前节点在进行其他判断。这里祖父18为红色,父节点为20黑色,不需要做任何修改,此时插入即完成,最终得到的结果如下:

再插入节点14,先判断,插入在节点15的左边,插入结果如下:

 可以看出,违反了红黑规则,所以对其进行判断修改,得出父节点15为红色,叔叔节点Nil为黑色,所以需要进行下面三步:

(1)将“父”设为黑色,修改后如下

(2)将“祖父”设为红色,修改后如下

(3)以祖父为支点进行右旋,这里旋转时不需要考虑Nil的,所以如下

 经右旋后,得到的结果如下:

 此时再进行判断,已经满足了红黑树的性质,插入完成!

各位觉得到这里就完了吗?我来提一个问题,如果我插入的不是14节点,而是16节点,又该怎么做呢?我先把插入前的图片重新粘贴在这里

我们来试一下吧!

先判断,16要插入到15的右侧

插入后得到结果为

 来进行判断,16的父节点15为红色,叔叔节点Nil为黑色,这是我们看规则,要求以父节点进行右旋,如下

 得到的旋转后的结果为

 这是我们再进行判断,此时判断要站在旋转支点15的基础上进行判断,15的父节点16为红色,叔叔节点为Nil黑色,此时各位就会发现,已经和上述插入节点14时的情况相同了,仍然是进行三步操作

(1)将“父”设为黑色,修改后如下

(2)将“祖父”设为红色,修改后如下

(3)以祖父为支点进行右旋,这里旋转时不需要考虑Nil的,如下所示:

 

 旋转后再将Nil进行补充得到最终结果

 此时我们再来判断,发现已经满足了红黑规则,插入完成。

OK,到这里关于红黑树的添加节点的规则就全部讲解完毕了。如果各位小伙伴哪里不懂的,可以多看几遍,仔细阅读我所描述的文字和所配的图片,相信一定能攻克困难,拿下红黑树。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
红黑树是一种自平衡的二叉查找树,它在插入和删除节点时能够保持树的平衡。红黑树的概念可以参考。在Java中实现红黑树,可以按照以下步骤进行: 1. 首先将红黑树当作一颗二叉查找树,将新节点插入到适当的位置上。 2. 将插入的节点着色为"红色"。 3. 根据红黑树的特性,通过一系列的旋转和着色等操作,使树重新保持红黑树的性质。 具体的插入过程可以参考中提供的代码。在代码中,使用了左旋转、右旋转和颜色翻转等操作来重新平衡红黑树。 首先,如果节点的右子树是红色而左子树是黑色,可以通过左旋转操作将其变为左子树为红色,右子树为黑色的情况。 其次,如果节点的左子树和左子树的左子树都是红色,可以通过右旋转操作将其修正为上述情况。 最后,如果节点的左子树和右子树都是红色,可以通过颜色翻转操作将其修正为左子树和右子树都为黑色的情况。 在插入完节点后,需要将根节点的颜色设置为黑色,以确保红黑树的性质满足。 这样,通过以上的步骤,就能够实现对红黑树的插入操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Java数据结构红黑树的真正理解](https://download.csdn.net/download/weixin_38622475/12770272)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Java高阶数据结构红黑树](https://blog.csdn.net/qq15035899256/article/details/126678970)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Java数据结构——红黑树](https://blog.csdn.net/weixin_30699463/article/details/95256212)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值