您当前的位置:首页 > 电脑百科 > 程序开发 > 算法

一文看懂 HashMap 中的红黑树实现原理

时间:2021-01-18 15:47:51  来源:  作者:

前言

本文咱们了解一下红黑树的设计,相比 jdk1.7 的 HashMap 而言,jdk1.8 最重要的就是引入了红黑树的设计,当冲突的链表长度超过 8 个的时候,链表结构就会转为红黑树结构。

01、故事的起因

JDK1.8 最重要的就是引入了红黑树的设计(当冲突的链表长度超过 8 个的时候),为什么要这样设计呢?好处就是避免在最极端的情况下冲突链表变得很长很长,在查询的时候,效率会非常慢。

 

一文看懂 HashMap 中的红黑树实现原理

 

  • 红黑树查询:其访问性能近似于折半查找,时间复杂度 O(logn);
  • 链表查询:这种情况下,需要遍历全部元素才行,时间复杂度 O(n);

本文主要是讲解红黑树的实现,只有充分理解了红黑树,对于之前的分析才会更加理解。

简单的说,红黑树是一种近似平衡的二叉查找树,其主要的优点就是“平衡“,即左右子树高度几乎一致,以此来防止树退化为链表,通过这种方式来保障查找的时间复杂度为 log(n)。

一文看懂 HashMap 中的红黑树实现原理

 

关于红黑树的内容,网上给出的内容非常多,主要有以下几个特性:

  • 1、每个节点要么是红色,要么是黑色,但根节点永远是黑色的;
  • 2、每个红色节点的两个子节点一定都是黑色;
  • 3、红色节点不能连续(也即是,红色节点的孩子和父亲都不能是红色);
  • 4、从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点;
  • 5、所有的叶节点都是是黑色的(注意这里说叶子节点其实是上图中的 NIL 节点);

在树的结构发生改变时(插入或者删除操作),往往会破坏上述条件 3 或条件 4,需要通过调整使得查找树重新满足红黑树的条件。

02、调整方式

上面已经说到当树的结构发生改变时,红黑树的条件可能被破坏,需要通过调整使得查找树重新满足红黑树的条件。

调整可以分为两类:一类是颜色调整,即改变某个节点的颜色,这种比较简单,直接将节点颜色进行转换即可;另一类是结构调整,改变检索树的结构关系。结构调整主要包含两个基本操作:左旋(Rotate Left),右旋(RotateRight)

2.1、左旋

左旋的过程是将 p 的右子树绕 p 逆时针旋转,使得 p 的右子树成为 p 的父亲,同时修改相关节点的引用,使左子树的深度加 1,右子树的深度减 1,通过这种做法来调整树的稳定性。过程如下:

一文看懂 HashMap 中的红黑树实现原理

 

以 jdk1.8 为例,打开 HashMap 的源码部分,红黑树内部类 TreeNode 属性分析:

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
		//指向父节点的指针
		TreeNode<K,V> parent;
		//指向左孩子的指针
 TreeNode<K,V> left;
		//指向右孩子的指针
 TreeNode<K,V> right;
		//前驱指针,跟next属性相反的指向
 TreeNode<K,V> prev;
		//是否为红色节点
 boolean red;
		......
}

左旋方法 rotateLeft 如下:

/*
 * 左旋逻辑
 */
static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,
 TreeNode<K,V> p) {
			//root:表示根节点
			//p:表示要调整的节点
			//r:表示p的右节点
			//pp:表示p的parent节点
			//rl:表示p的右孩子的左孩子节点
 TreeNode<K,V> r, pp, rl;
			//r判断,如果r为空则旋转没有意义
 if (p != null && (r = p.right) != null) {
				//多个等号的连接操作从右往左看,设置rl的父亲为p
 if ((rl = p.right = r.left) != null)
 rl.parent = p;
				//判断p的父亲,为空,为根节点,根节点的话就设置为黑色
 if ((pp = r.parent = p.parent) == null)
 (root = r).red = false;
				//判断p节点是左儿子还是右儿子
 else if (pp.left == p)
 pp.left = r;
 else
 pp.right = r;
 r.left = p;
 p.parent = r;
 }
 return root;
}

2.2、右旋

了解了左旋转之后,相应的就会有右旋,逻辑基本也是一样,只是方向变了。右旋的过程是将 p 的左子树绕 p 顺时针旋转,使得 p 的左子树成为 p 的父亲,同时修改相关节点的引用,使右子树的深度加 1,左子树的深度减 1,通过这种做法来调整树的稳定性。实现过程如下:

一文看懂 HashMap 中的红黑树实现原理

 

同样的,右旋方法 rotateRight 如下:

/*
 * 右旋逻辑
 */
static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,
 TreeNode<K,V> p) {
			//root:表示根节点
			//p:表示要调整的节点
			//l:表示p的左节点
			//pp:表示p的parent节点
			//lr:表示p的左孩子的右孩子节点
 TreeNode<K,V> l, pp, lr;
			//l判断,如果l为空则旋转没有意义
 if (p != null && (l = p.left) != null) {
				//多个等号的连接操作从右往左看,设置lr的父亲为p
 if ((lr = p.left = l.right) != null)
 lr.parent = p;
				//判断p的父亲,为空,为根节点,根节点的话就设置为黑色
 if ((pp = l.parent = p.parent) == null)
 (root = l).red = false;
				//判断p节点是右儿子还是左儿子
 else if (pp.right == p)
 pp.right = l;
 else
 pp.left = l;
 l.right = p;
 p.parent = l;
 }
 return root;
}

03、操作示例介绍

3.1、插入调整过程图解

一文看懂 HashMap 中的红黑树实现原理

 

3.2、删除调整过程图解

一文看懂 HashMap 中的红黑树实现原理

 

3.3、查询过程图解

一文看懂 HashMap 中的红黑树实现原理

 

04、总结

至此,红黑树的实现就基本完成了,关于红黑树的结构,有很多种情况,情况也比较复杂,但是整体调整流程,基本都是先调整结构然后调整颜色,直到最后满足红黑树特性要求为止。



Tags:HashMap   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
1、HashMap主要成员变量size 记录了 Map 中 KV 对的个数。loadFactor 装载印子,用来衡量 HashMap 满的程度。loadFactor 的默认值为 0.75f。threshold 临界值,当实际 KV 个数...【详细内容】
2021-06-08  Tags: HashMap  点击:(152)  评论:(0)  加入收藏
场景描述我们在日常学习和研发中,经常会接触一些底层的源码,有些同学在遇到位运算(提高系统的运行效率)实现的方法时,读起来就有些吃力了,例如HashMap类中的tableSizeFor(int cap...【详细内容】
2021-04-06  Tags: HashMap  点击:(247)  评论:(0)  加入收藏
前言本文咱们了解一下红黑树的设计,相比 jdk1.7 的 HashMap 而言,jdk1.8 最重要的就是引入了红黑树的设计,当冲突的链表长度超过 8 个的时候,链表结构就会转为红黑树结构。01、...【详细内容】
2021-01-18  Tags: HashMap  点击:(173)  评论:(0)  加入收藏
本节让我们一起研究一下该容器是如何在保证线程安全的同时又能保证高效的操作。 ConcurrentHashMap 是线程安全且高效的 HashMap 。...【详细内容】
2020-10-16  Tags: HashMap  点击:(79)  评论:(0)  加入收藏
絮叨学校短学期刚结束了,离学校开学还有很多天,一直呆在寝室玩游戏岂不是浪费了大好时光,于是心血来潮想看看HashMap的源码。虽然我没有经历过面试,但是java程序员都知道,HashMap...【详细内容】
2020-09-27  Tags: HashMap  点击:(59)  评论:(0)  加入收藏
一、前言得益于Doug Lea老爷子的操刀,让HashMap成为使用和面试最频繁的API,没办法设计的太优秀了!HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现。HashMap 允许 null 键和...【详细内容】
2020-08-11  Tags: HashMap  点击:(46)  评论:(0)  加入收藏
TL:DR他们将键映射到值。哈希映射可能是映射概念最常用的实现。 它们允许将任意对象与其他任意对象关联。这对于执行诸如通过某些公共属性将数据分组或连接在一起之类的工作...【详细内容】
2020-07-19  Tags: HashMap  点击:(69)  评论:(0)  加入收藏
jdk1.7中的底层实现过程(底层基于数组+链表)在我们new HashMap()时,底层创建了默认长度为16的一维数组Entry[ ] table。当我们调用map.put(key1,value1)方法向HashMap里添加数...【详细内容】
2020-06-28  Tags: HashMap  点击:(40)  评论:(0)  加入收藏
通过Map.values()遍历所有的value,不能遍历key public class TestDemo{ public static void main(String[] args) { HashMap<String,String> hashMap = new Has...【详细内容】
2020-03-08  Tags: HashMap  点击:(47)  评论:(0)  加入收藏
HashMap是数组+链表实现的,既然用到hash散列,那么肯定不可避免的会出现冲突问题,HashMap解决冲突的方法是拉链法,因为这里有用到数组,那么当容量不足的时候就需要进行扩容操作了...【详细内容】
2019-10-24  Tags: HashMap  点击:(116)  评论:(0)  加入收藏
▌简易百科推荐
前言Kafka 中有很多延时操作,比如对于耗时的网络请求(比如 Produce 是等待 ISR 副本复制成功)会被封装成 DelayOperation 进行延迟处理操作,防止阻塞 Kafka请求处理线程。Kafka...【详细内容】
2021-12-27  Java技术那些事    Tags:时间轮   点击:(1)  评论:(0)  加入收藏
博雯 发自 凹非寺量子位 报道 | 公众号 QbitAI在炼丹过程中,为了减少训练所需资源,MLer有时会将大型复杂的大模型“蒸馏”为较小的模型,同时还要保证与压缩前相当的结果。这就...【详细内容】
2021-12-24  量子位    Tags:蒸馏法   点击:(9)  评论:(0)  加入收藏
分稀疏重建和稠密重建两类:稀疏重建:使用RGB相机SLAMOrb-slam,Orb-slam2,orb-slam3:工程地址在: http://webdiis.unizar.es/~raulmur/orbslam/ DSO(Direct Sparse Odometry)因为...【详细内容】
2021-12-23  老师明明可以靠颜值    Tags:算法   点击:(7)  评论:(0)  加入收藏
1. 基本概念希尔排序又叫递减增量排序算法,它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的;希尔排序是一种不稳定的排序算法...【详细内容】
2021-12-22  青石野草    Tags:希尔排序   点击:(6)  评论:(0)  加入收藏
ROP是一种技巧,我们对execve函数进行拼凑来进行system /bin/sh。栈迁移的特征是溢出0x10个字符,在本次getshell中,还碰到了如何利用printf函数来进行canary的泄露。ROP+栈迁移...【详细内容】
2021-12-15  星云博创    Tags:栈迁移   点击:(19)  评论:(0)  加入收藏
一、什么是冒泡排序1.1、文字描述冒泡排序是一种简单的排序算法。它重复地走访要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地...【详细内容】
2021-12-15    晓掌柜丶韶华  Tags:排序算法   点击:(16)  评论:(0)  加入收藏
在了解golang的map之前,我们需要了解哈希这个概念。哈希表,又称散列表(Hash table),是根据键(key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算出一个键值的函数,将...【详细内容】
2021-12-07  一棵梧桐木    Tags:哈希表   点击:(13)  评论:(0)  加入收藏
前面文章在谈论分布式唯一ID生成的时候,有提到雪花算法,这一次,我们详细点讲解,只讲它。SnowFlake算法据国家大气研究中心的查尔斯&middot;奈特称,一般的雪花大约由10^19个水分子...【详细内容】
2021-11-17  小心程序猿QAQ    Tags:雪花算法   点击:(24)  评论:(0)  加入收藏
导读:在大数据时代,对复杂数据结构中的各数据项进行有效的排序和查找的能力非常重要,因为很多现代算法都需要用到它。在为数据恰当选择排序和查找策略时,需要根据数据的规模和类型进行判断。尽管不同策略最终得到的结果完...【详细内容】
2021-11-04  华章科技    Tags:排序算法   点击:(37)  评论:(0)  加入收藏
这是我在网上找的资源的一个总结,会先给出一个我看了觉得还行的关于算法的讲解,再配上实现的代码: Original author: Bill_Hoo Original Address: http://blog.sina.com.cn/s/bl...【详细内容】
2021-11-04  有AI野心的电工和码农    Tags: KMP算法   点击:(36)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条