后台开发:核心技术与应用实践3.4.3 map的原理

简介:

3.4.3 map的原理


map内部自建一棵红黑树(一种非严格意义上的平衡二叉树),这棵树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。这里简单讲下红黑树的含义。

先来看下算法导论对R-B Tree的介绍:红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。红黑树,作为一棵二叉查找树,满足二叉查找树的一般性质。下面,来了解下二叉查找树的一般性质。

二叉查找树,也称有序二叉树(ordered binary tree),或已排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树:①若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;②若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;③任意节点的左、右子树也分别为二叉查找树;④没有键值相等的节点(no duplicate node)。

因为一棵由n个结点随机构造的二叉查找树的高度为lgn,所以二叉查找树的一般操作的执行时间为O(lgn)。但二叉查找树若退化成了一棵具有n个结点的线性链后,则这些操作最坏情况运行时间为O(n)。

红黑树虽然本质上是一棵二叉查找树,但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡,从而保证了红黑树的查找、插入、删除的时间复杂度最坏为O(logn)。

它是如何保证一棵n个结点的红黑树的高度始终保持在logn的呢?这就引出了红黑树的5个性质:①每个结点要么是红的要么是黑的;②根结点是黑的;③每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的;④如果一个结点是红的,那么它的两个儿子都是黑的;⑤对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。

正是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logn的高度,从而也就解释了上面所说的“红黑树的查找、插入、删除的时间复杂度最坏为O(logn)”这一结论成立的原因。

如图3-3所示,是一颗红黑树(图3-3引自wikipedia:http://t.cn/hgvH1l)。

 

图3-3 红黑树

当在对红黑树进行插入和删除等操作时,对树做了修改可能会破坏红黑树的性质。为了继续保持红黑树的性质,可以通过对结点进行重新着色,以及对树进行相关的旋转操作,即通过修改树中某些结点的颜色及指针结构,来达到对红黑树进行插入或删除结点等操作后继续保持它的性质或平衡的目的。

树的旋转分为左旋和右旋,下面借助图来介绍一下左旋和右旋这两种操作。

1)左旋操作(图3-4)。

 

图3.4 左旋操作示意图

如图3-4所示,当在某个结点pivot上,做左旋操作时,假设它的右孩子y不是NIL[T],pivot可以为任何不是NIL[T]的左子结点。左旋以pivot到Y之间的链为“支轴”进行,它使Y成为该子树的新根,而Y的左孩子b则成为pivot的右孩子,在代码中表示如下所示。

LeftRoate(T, x)

y ← x.right            // y是x的右孩子

x.right ← y.left             // y的左孩子成为x的右孩子

if y.left ≠ T.nil

    y.left.p ← x

y.p ← x.p                   // y成为x的父亲

if x.p = T.nil

    then T.root ← y

else if x = x.p.left

    then x.p.left ← y

else x.p.right ← y

y.left ← x              // x作为y的左孩子

x.p ← y

2)右旋操作(图3-5)。

 

图3-5 右旋操作示意图

右旋与左旋差不多,再此不做详细介绍。

树在经过左旋右旋之后,树的搜索性质保持不变,但树的红黑性质被破坏了,所以红黑树插入和删除数据后,需要利用旋转与颜色重涂来重新恢复树的红黑性质。

由于map的内部实现过于复杂,本章不做详细介绍,有兴趣的读者可自行在网上查资料。

相关文章
|
25天前
|
设计模式 前端开发 Java
【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究SpringMVC的核心原理和运作机制(总体框架原理篇)
【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究SpringMVC的核心原理和运作机制(总体框架原理篇)
30 0
|
4月前
|
Java API 容器
资深Java大牛带你由基础到原理再到项目实战,轻松掌控核心技术
《Java编程的逻辑》致力于帮助读者真正理解Java编程。对于每个语言特性和API,不仅介绍其概念和用法,还分析了为什么要有这个概念,实现原理是什么,背后的思维逻辑是什么;对于类库,分析了大量源码,使读者不仅知其然,还知其所以然,以透彻理解相关知识点。
资深Java大牛带你由基础到原理再到项目实战,轻松掌控核心技术
|
5月前
|
Java 大数据 开发者
Java学习之路:扎实基础、掌握核心特性、多实践交流,成为优秀开发者!
Java学习之路:扎实基础、掌握核心特性、多实践交流,成为优秀开发者!
|
消息中间件 缓存 监控
阿里藏经阁天花板:高性能Java架构核心原理手册,一定要偷偷看
市面上讲Java框架的书很多,包括Sping Boot、Spring Cloud、Kafka等,但这些书通常只会让你技术的“量”增长,而“质”仍处于SSM的阶段。而且互联网上并没有体系化、结构化的提升技术的“质”的教材,于是这份阿里的高性能java架构核心手册就出来了!
阿里藏经阁天花板:高性能Java架构核心原理手册,一定要偷偷看
|
SQL 缓存 监控
SSM框架源码分析:助你深入理解底层原理,提高核心竞争力
众所周知SSM源码分析教程里面包括Mybatis、Spring以及SpringMVC这三个经典的开源框架的源码分析。我们编程人员技术提升逃不过的一个重要方式就是阅读和理解优秀开源项目的源码,通过阅读和理解优秀开源项目的源码掌握开源项目它底层是如何实现的,领悟大师级的设计思想,开阔自己的视野。在自己实践开发中可以借鉴和参考,以提升自己的(拍晕面试官)阅读复杂代码的能力,以及修炼自我的编码功底。 本套课程就是带你去阅读Mybatis、Spring以及SpringMVC这三个开源框架的源码,掌握这些开源框架的底层原理、执行流程以及它是如何实现的,让你对这些开源框架不再是停留在如何使用的层面,来提高自
172 0
|
缓存 运维 Kubernetes
前端高级进阶:前端部署的发展历程
前端高级进阶:javascript 代码是如何被压缩 前端高级进阶:如何更好地优化打包资源 前端高级进阶:网站的缓存控制策略最佳实践及注意事项 前端高级进阶:在生产环境中使你的 npm i 速度提升 50% 前端高级进阶:使用 docker 高效部署你的前端应用 前端高级进阶:CICD 下的前端多特性分支环境的部署 前端高级进阶:前端部署的发展历程 更多文章: 前端工程化系列 我在 github 上新建了一个仓库 每日一题,每天一道面试题,欢迎交流。 前端面试题小记 前端大厂面经大全集 计算机基础面试题小计 前端一说起刀耕火种,那肯定紧随着前端工程化这一话题。随着 react/vue/ang
239 0
|
监控 JavaScript 前端开发

热门文章

最新文章