(纯干货,非水文)一文1.5w字30图,彻底通透理解红黑树

红黑树的实现原理和应用场景 红黑树(Red-Black Tree)是一种自平衡的二叉查找树,它通过特定的规则确保树在插入和删除操作后能保持相对平衡,从而保证查找、插入、删除等操作的时间复杂度为O(log n)。红黑树是一种高效的自平衡二叉查找树,通过精心设计的平衡规则和旋转操作,在各种动态数据管理场景中表现出色。虽然实现相对复杂,但其优秀的综合性能使其成为许多高级数据结构和系统组件的首选实现方式。理解红黑树的原理和实现,对于深入掌握计算机科学中的数据结构和算法设计具有重要意义。 阅读详情

写在前面

当在10亿数据进行不到30次比较就能查找到目标时,不禁感叹编程之魅力!人类之伟大呀! —— 学红黑树有感。

终于,在学习了几天的红黑树相关的知识后,我想把我所学所想和所感分享给大家。红黑树是一种比较难的数据结构,要完全搞懂非常耗时耗力,红黑树怎么自平衡?什么时候需要左旋或右旋?插入和删除破坏了树的平衡后怎么处理?等等一连串的问题在学习前困扰着我。如果你在学习过程中也会存在我的疑问,那么本文对你会有帮助,本文帮助你全面、彻底地理解红黑树!

本文将通过图文的方式讲解红黑树的知识点,并且不会涉及到任何代码,相信我,在懂得红黑树实现原理前,看代码会一头雾水的,当原理懂了,代码也就按部就班写而已,没任何难度。

阅读本文你需具备知识点:

  • 二叉查找树
  • 完美平衡二叉树

事不宜迟,让我们进入正题吧。

欢迎各位大佬进群共同交流学习,我们的交流分享群:1149778920 暗号:优快云
博主在这里给大家整理了包括但不限于:JAVA基础和进阶类、Spring、Spring boot、Spring MVC、MyBatis、MySQL、JVM等各种资料有,免费分享给各位进群的小伙伴

在这里插入图片描述

正文

红黑树也是二叉查找树,我们知道,二叉查找树这一数据结构并不难,而红黑树之所以难是难在它是自平衡的二叉查找树,在进行插入和删除等可能会破坏树的平衡的操作时,需要重新自处理达到平衡状态。现在在脑海想下怎么实现?是不是太多情景需要考虑了?啧啧,先别急,通过本文的学习后,你会觉得,其实也不过如此而已。好吧,我们先来看下红黑树的定义和一些基本性质。

红黑树定义和性质
红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:

  • 性质1:每个节点要么是黑色,要么是红色。

  • 性质2:根节点是黑色。

  • 性质3:每个叶子节点(NIL)是黑色。

  • 性质4:每个红色结点的两个子结点一定都是黑色。

  • 性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。
    从性质5又可以推出:

  • 性质5.1:如果一个结点存在黑子结点,那么该结点肯定有两个子结点
    下图就是一颗简单的红黑树。其中Nil为叶子结点,并且它是黑色的。(值得提醒注意的是,在Java中,叶子结点是为null的结点。)

在这里插入图片描述
红黑树并不是一个完美平衡二叉查找树,从图1可以看到,根结点P的左子树显然比右子树高,但左子树和右子树的黑结点的层数是相等的,也即任意一个结点到到每个叶子结点的路径都包含数量相同的黑结点(性质5)。所以我们叫红黑树这种平衡为黑色完美平衡。

介绍到此,为了后面讲解不至于混淆,我们还需要来约定下红黑树一些结点的叫法,如下图所示。

在这里插入图片描述
我们把正在处理(遍历)的结点叫做当前结点,如图2中的D,它的父亲叫做父结点,它的父亲的另外一个子结点叫做兄弟结点,父亲的父亲叫做祖父结点。

前面讲到红黑树能自平衡,它靠的是什么?三种操作:左旋、右旋和变色。

  • 左旋:以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。如下图。

在这里插入图片描述

  • 右旋:以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。如下图。

在这里插入图片描述

  • 变色:结点的颜色由红变黑或由黑变红。

上面所说的旋转结点也即旋转的支点

我们先忽略颜色,可以看到旋转操作不会影响旋转结点的父结点,父结点以上的结构还是保持不变的。

左旋只影响旋转结点和其右子树的结构,把右子树的结点往左子树挪了。
右旋只影响旋转结点和其左子树的结构,把左子树的结点往右子树挪了。

所以旋转操作是局部的。另外可以看出旋转能保持红黑树平衡的一些端详了:当一边子树的结点少了,那么向另外一边子树“借”一些结点;当一边子树的结点多了,那么向另外一边子树“租”一些结点。

但要保持红黑树的性质,结点不能乱挪,还得靠变色了。怎么变?具体情景又不同变法,后面会具体讲到,现在只需要记住红黑树总是通过旋转和变色达到自平衡。

balabala了这么多,相信你对红黑树有一定印象了,那么现在来考考你:

思考题1:黑结点可以同时包含一个红子结点和一个黑子结点吗? (答案见文末)

接下来先讲解红黑树的查找热热身。

红黑树查找

因为红黑树是一颗二叉平衡树,并且查找不会破坏树的平衡,所以查找跟二叉平衡树的查找无异:

  • 从根结点开始查找,把根结点设置为当前结点;
  • 若当前结点为空,返回null;
  • 若当前结点不为空,用当前结点的key跟查找key作比较;
  • 若当前结点key等于查找key,那么该key就是查找目标,返回当前结点;
  • 若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤2;
  • 若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤2;

如下图所示。

在这里插入图片描述
非常简单,但简单不代表它效率不好。正由于红黑树总保持黑色完美平衡,所以它的查找最坏时间复杂度为O(2lgN),也即整颗树刚好红黑相隔的时候。能有这么好的查找效率得益于红黑树自平衡的特性,而这背后的付出,红黑树的插入操作功不可没~

红黑树插入

插入操作包括两部分工作:一查找插入的位置;二插入后自平衡。查找插入的父结点很简单,跟查找操作区别不大:

  • 从根结点开始查找;
  • 若根结点为空,那么插入结点作为根结点,结束。
  • 若根结点不为空,那么把根结点作为当前结点;
  • 若当前结点为null,返回当前结点的父结点,结束。
  • 若当前结点key等于查找key,那么该key所在结点就是插入结点,更新结点的值,结束。
  • 若当前结点key大于查找key,把当前结点的左子结点设置为当前结点,重复步骤4;
  • 若当前结点key小于查找key,把当前结点的右子结点设置为当前结点,重复步骤4;

如下图所示。

在这里插入图片描述
ok,插入位置已经找到,把插入结点放到正确的位置就可以啦,但插入结点是应该是什么颜色呢?答案是红色。理由很简单,红色在父结点(如果存在)为黑色结点时,红黑树的黑色平衡没被破坏,不需要做自平衡操作。但如果插入结点是黑色,那么插入位置所在的子树黑色结点总是多1,必须做自平衡。

所有插入情景如下图所示。

在这里插入图片描述
嗯,插入情景很多呢,8种插入情景!但情景1、2和3的处理很简单,而情景4.2和情景4.3只是方向反转而已,懂得了一种情景就能推出另外一种情景,所以总体来看,并不复杂,后续我们将一个一个情景来看,把它彻底搞懂。

另外,根据二叉树的性质,除了情景2,所有插入操作都是在叶子结点进行的。这点应该不难理解,因为查找插入位置时,我们就是在找子结点为空的父结点的。

在开始每个情景的讲解前,我们还是先来约定下,如下图所示。

在这里插入图片描述
字母并不代表结点Key的大小。I表示插入结点,P表示插入结点的父结点,S表示插入结点的叔叔结点,PP表示插入结点的祖父结点。

好了,下面让我们一个一个来分析每个插入的情景以其处理。

插入情景1:红黑树为空树

最简单的一种情景,直接把插入结点作为根结点就行,但注意,根据红黑树性质2:根节点是黑色。还需要把插入结点设为黑色。

处理:

  • 把插入结点作为根结点,并把结点设置为黑色。

插入情景2:插入结点的Key已存在

插入结点的Key已存在,既然红黑树总保持平衡,在插入前红黑树已经是平衡的,那么把插入结点设置为将要替代结点的颜色,再把结点的值更新就完成插入。

处理:

  • 把I设为当前结点的颜色
  • 更新当前结点的值为插入结点的值

插入情景3:插入结点的父结点为黑结点

由于插入的结点是红色的,当插入结点的黑色时,并不会影响红黑树的平衡,直接插入即可,无需做自平衡。

处理:

  • 直接插入。

插入情景4:插入结点的父结点为红结点

再次回想下红黑树的性质2:根结点是黑色。如果插入的父结点为红结点,那么该父结点不可能为根结点,所以插入结点总是存在祖父结点。这点很重要,因为后续的旋转操作肯定需要祖父结点的参与。

情景4又分为很多子情景,下面将进入重点部分,各位看官请留神了。

插入情景4.1:叔叔结点存在并且为红结点
从红黑树性质4可以,祖父结点肯定为黑结点,因为不可以同时存在两个相连的红结点。那么此时该插入子树的红黑层数的情况是:黑红红。显然最简单的处理方式是把其改为:红黑红。如图4.1和图4.2所示。

处理:

  • 将P和S设置为黑色
  • 将PP设置为红色
  • 把PP设置为当前插入结点

在这里插入图片描述
在这里插入图片描述
可以看到,我们把PP结点设为红色了,如果PP的父结点是黑色,那么无需再做任何处理;但如果PP的父结点是红色,根据性质4,此时红黑树已不平衡了,所以还需要把PP当作新的插入结点,继续做插入操作自平衡处理,直到平衡为止。

试想下PP刚好为根结点时,那么根据性质2,我们必须把PP重新设为黑色,那么树的红黑结构变为:黑黑红。换句话说,从根结点到叶子结点的路径中,黑色结点增加了。这也是唯一一种会增加红黑树黑色结点层数的插入情景。

我们还可以总结出另外一个经验:红黑树的生长是自底向上的。这点不同于普通的二叉查找树,普通的二叉查找树的生长是自顶向下的。

插入情景4.2:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的左子结点
单纯从插入前来看,也即不算情景4.1自底向上处理时的情况,叔叔结点非红即为叶子结点(Nil)。因为如果叔叔结点为黑结点,而父结点为红结点,那么叔叔结点所在的子树的黑色结点就比父结点所在子树的多了,这不满足红黑树的性质5。后续情景同样如此,不再多做说明了。

前文说了,需要旋转操作时,肯定一边子树的结点多了或少了,需要租或借给另一边。插入显然是多的情况,那么把多的结点租给另一边子树就可以了。

插入情景4.2.1:插入结点是其父结点的左子结点
处理:

  • 将P设为黑色
  • 将PP设为红色
  • 对PP进行右旋

在这里插入图片描述

由上图可得,左边两个红结点,右边不存在,那么一边一个刚刚好,并且因为为红色,肯定不会破坏树的平衡。

咦,可以把P设为红色,I和PP设为黑色吗?答案是可以!看过《算法:第4版》的同学可能知道,书中讲解的就是把P设为红色,I和PP设为黑色。但把P设为红色,显然又会出现情景4.1的情况,需要自底向上处理,做多了无谓的操作,既然能自己消化就不要麻烦祖辈们啦~

插入情景4.2.2:插入结点是其父结点的右子结点

这种情景显然可以转换为情景4.2.1,如图下所示,不做过多说明了。

处理:

  • 对P进行左旋
  • 把P设置为插入结点,得到情景4.2.1
  • 进行情景4.2.1的处理

在这里插入图片描述

插入情景4.3:叔叔结点不存在或为黑结点,并且插入结点的父亲结点是祖父结点的右子结点

该情景对应情景4.2,只是方向反转,不做过多说明了,直接看图。

插入情景4.3.1:插入结点是其父结点的右子结点

处理:

  • 将P设为黑色
  • 将PP设为红色
  • 对PP进行左旋

在这里插入图片描述
插入情景4.3.2:插入结点是其父结点的左子结点

处理:

  • 对P进行右旋
  • 把P设置为插入结点,得到情景4.3.1
  • 进行情景4.3.1的处理

在这里插入图片描述

好了,讲完插入的所有情景了。可能又同学会想:上面的情景举例的都是第一次插入而不包含自底向上处理的情况,那么上面所说的情景都适合自底向上的情况吗?答案是肯定的。理由很简单,但每棵子树都能自平衡,那么整棵树最终总是平衡的。好吧,在出个习题,请大家拿出笔和纸画下试试(请务必动手画下,加深印象):

习题1:请画出下图的插入自平衡处理过程。(答案见文末)

在这里插入图片描述

红黑树删除

红黑树插入已经够复杂了,但删除更复杂,也是红黑树最复杂的操作了。但稳住,胜利的曙光就在前面了!

红黑树的删除操作也包括两部分工作:一查找目标结点;而删除后自平衡。查找目标结点显然可以复用查找操作,当不存在目标结点时,忽略本次操作;当存在目标结点时,删除后就得做自平衡处理了。删除了结点后我们还需要找结点来替代删除结点的位置,不然子树跟父辈结点断开了,除非删除结点刚好没子结点,那么就不需要替代。

二叉树删除结点找替代结点有3种情情景:

  • 情景1:若删除结点无子结点,直接删除
  • 情景2:若删除结点只有一个子结点,用子结点替换删除结点
  • 情景3:若删除结点有两个子结点,用后继结点(大于删除结点的最小结点)替换删除结点

补充说明下,情景3的后继结点是大于删除结点的最小结点,也是删除结点的右子树种最左结点。那么可以拿前继结点(删除结点的左子树最右结点)替代吗?可以的。但习惯上大多都是拿后继结点来替代,后文的讲解也是用后继结点来替代。另外告诉大家一种找前继和后继结点的直观的方法(不知为何没人提过,大家都知道?):把二叉树所有结点投射在X轴上,所有结点都是从左到右排好序的,所有目标结点的前后结点就是对应前继和后继结点。如下图所示。

在这里插入图片描述
接下来,讲一个重要的思路:删除结点被替代后,在不考虑结点的键值的情况下,对于树来说,可以认为删除的是替代结点!话很苍白,我们看下图。在不看键值对的情况下,图17的红黑树最终结果是删除了Q所在位置的结点!这种思路非常重要,大大简化了后文讲解红黑树删除的情景!

在这里插入图片描述

基于此,上面所说的3种二叉树的删除情景可以相互转换并且最终都是转换为情景1!

  • 情景2:删除结点用其唯一的子结点替换,子结点替换为删除结点后,可以认为删除的是子结点,若子结点又有两个子结点,那么相当于转换为情景3,一直自顶向下转换,总是能转换为情景1。(对于红黑树来说,根据性质5.1,只存在一个子结点的结点肯定在树末了)

  • 情景3:删除结点用后继结点(肯定不存在左结点),如果后继结点有右子结点,那么相当于转换为情景2,否则转为为情景1。

二叉树删除结点情景关系图如图所示。

在这里插入图片描述

综上所述,删除操作删除的结点可以看作删除替代结点,而替代结点最后总是在树末。有了这结论,我们讨论的删除红黑树的情景就少了很多,因为我们只考虑删除树末结点的情景了。

同样的,我们也是先来总体看下删除操作的所有情景,如下图所示。

在这里插入图片描述
哈哈,是的,即使简化了还是有9种情景!但跟插入操作一样,存在左右对称的情景,只是方向变了,没有本质区别。同样的,我们还是来约定下,如下图所示。

在这里插入图片描述
上图的字母并不代表结点Key的大小。R表示替代结点,P表示替代结点的父结点,S表示替代结点的兄弟结点,SL表示兄弟结点的左子结点,SR表示兄弟结点的右子结点。灰色结点表示它可以是红色也可以是黑色。

值得特别提醒的是,R是即将被替换到删除结点的位置的替代结点,在删除前,它还在原来所在位置参与树的子平衡,平衡后再替换到删除结点的位置,才算删除完成。

万事具备,我们进入最后的也是最难的讲解。

删除情景1:替换结点是红色结点
我们把替换结点换到了删除结点的位置时,由于替换结点时红色,删除也了不会影响红黑树的平衡,只要把替换结点的颜色设为删除的结点的颜色即可重新平衡。

处理:

  • 颜色变为删除结点的颜色

删除情景2:替换结点是黑结点
当替换结点是黑色时,我们就不得不进行自平衡处理了。我们必须还得考虑替换结点是其父结点的左子结点还是右子结点,来做不同的旋转操作,使树重新平衡。

删除情景2.1:替换结点是其父结点的左子结点

删除情景2.1.1:替换结点的兄弟结点是红结点
若兄弟结点是红结点,那么根据性质4,兄弟结点的父结点和子结点肯定为黑色,不会有其他子情景,我们按图21处理,得到删除情景2.1.2.3(后续讲解,这里先记住,此时R仍然是替代结点,它的新的兄弟结点SL和兄弟结点的子结点都是黑色)。

处理:

  • 将S设为黑色
  • 将P设为红色
  • 对P进行左旋,得到情景2.1.2.3
  • 进行情景2.1.2.3的处理

在这里插入图片描述
删除情景2.1.2:替换结点的兄弟结点是黑结点
当兄弟结点为黑时,其父结点和子结点的具体颜色也无法确定(如果也不考虑自底向上的情况,子结点非红即为叶子结点Nil,Nil结点为黑结点),此时又得考虑多种子情景。

删除情景2.1.2.1:替换结点的兄弟结点的右子结点是红结点,左子结点任意颜色
即将删除的左子树的一个黑色结点,显然左子树的黑色结点少1了,然而右子树又又红色结点,那么我们直接向右子树“借”个红结点来补充黑结点就好啦,此时肯定需要用旋转处理了。如下图所示。

处理:

  • 将S的在这里插入图片描述
    设为P的颜色
  • 将P设为黑色
  • 将SR设为黑色
  • 对P进行左旋

平衡后的图怎么不满足红黑树的性质?前文提醒过,R是即将替换的,它还参与树的自平衡,平衡后再替换到删除结点的位置,所以R最终可以看作是删除的。另外上图是考虑到第一次替换和自底向上处理的情况,如果只考虑第一次替换的情况,根据红黑树性质,SL肯定是红色或为Nil,所以最终结果树是平衡的。如果是自底向上处理的情况,同样,每棵子树都保持平衡状态,最终整棵树肯定是平衡的。后续的情景同理,不做过多说明了。

删除情景2.1.2.2:替换结点的兄弟结点的右子结点为黑结点,左子结点为红结点
兄弟结点所在的子树有红结点,我们总是可以向兄弟子树借个红结点过来,显然该情景可以转换为情景2.1.2.1。下图所示。

处理:

将S设为红色
将SL设为黑色
对S进行右旋,得到情景2.1.2.1
进行情景2.1.2.1的处理

在这里插入图片描述

删除情景2.1.2.3:替换结点的兄弟结点的子结点都为黑结点

好了,此次兄弟子树都没红结点“借”了,兄弟帮忙不了,找父母呗,这种情景我们把兄弟结点设为红色,再把父结点当作替代结点,自底向上处理,去找父结点的兄弟结点去“借”。但为什么需要把兄弟结点设为红色呢?显然是为了在P所在的子树中保证平衡(R即将删除,少了一个黑色结点,子树也需要少一个),后续的平衡工作交给父辈们考虑了,还是那句,当每棵子树都保持平衡时,最终整棵总是平衡的。

处理:

  • 将S设为红色
  • 把P作为新的替换结点
  • 重新进行删除结点情景处理

在这里插入图片描述
综上,红黑树删除后自平衡的处理可以总结为:

  • 自己能搞定的自消化(情景1)
  • 自己不能搞定的叫兄弟帮忙(除了情景1、情景2.1.2.3和情景2.2.2.3)
  • 兄弟都帮忙不了的,通过父母,找远方亲戚(情景2.1.2.3和情景2.2.2.3)
    哈哈,是不是跟现实中很像,当我们有困难时,首先先自己解决,自己无力了总兄弟姐妹帮忙,如果连兄弟姐妹都帮不上,再去找远方的亲戚了。这里记忆应该会好记点~

最后再做个习题加深理解(请不熟悉的同学务必动手画下):

习题2:请画出图29的删除自平衡处理过程。

在这里插入图片描述

写在后面

耗时良久,终于写完了~自己加深了红黑树的理解的同时,也希望能帮助大家。如果你之前没学习过红黑树,看完这篇文章后可能还存在很多疑问,如果有疑问可以在评论区写出来,我会尽自己所能解答。另外给大家推荐一个支持红黑树在线生成的网站,来做各种情景梳理很有帮助:在线生成红黑树。(删除操作那个把替代结点看作删除结点思路就是我自己在用这个网站时自己顿悟的,我觉得这样讲解更容易理解。)

少了代码是不是觉得有点空虚?哈哈,后续我会写关于Java和HashMap和TreeMap的文章,里面都有红黑树相关的知识。相信看了这篇文章后,再去看Java和HashMap和TreeMap的源码绝对没难度!

博主在这里给大家发个福利~
这里整理了20多家公司的真实面试经历,以及各种关于Spring、Spring boot、Spring MVC、MyBatis、MySQL、JVM等知识点,如果有需要的小伙伴可以加群1149778920 来自行领取 暗号:优快云
以下是部分资料截图(所有资料均已整合成文档,pdf压缩打包处理)。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

最后来看下思考题和习题的答案吧。

思考题和习题答案

思考题1:黑结点可以同时包含一个红子结点和一个黑子结点吗?

答:可以。如下图的F结点:

在这里插入图片描述

习题1:请画出插入自平衡处理过程。

答:

在这里插入图片描述

习题2:请画出删除自平衡处理过程。

答:

在这里插入图片描述

HashMap 的实现原理和扩容原理是怎样的? HashMap 的实现原理和扩容原理是怎样的?一、实现原理1.1 哈希表1.1.1 概述1.1.2 哈希冲突1.2 存储分析1.3 hash 算法1.4 put 方法源码分析1.5 get 方法源码分析1.6 总结二、扩容机制2.1 什么时候发生扩容2.2 jdk1.8 中的扩容机制三、最后 一、实现原理 1.1 哈希表 1.1.1 概述 要学习 hashmap,就不得不提哈希表。 维基百科定义如下: 散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存储存位置的数据结构。也就是 阅读详情

相关推荐

关于hashMap扩容

例子1: HashMap<Integer, Integer> map = new HashMap<>(16, 2); for (int i = 0; i < 40; i++) { map.put(i, i); } 描述:创建map对象长度是16,阈值为32的map对象。阈值的计算16*2=32,阈值的作用是,, 当向map对象添加超过32条数据时,也就是当添加到底33条数据时,要进行扩容。如果不设置默认加

qq_42373704的博客 2151

关于HashMap扩容机制

HashMap的底层有数组 + 链表(红黑树)组成,数组的大小可以在构造方法时设置,默认大小为16,数组中每一个元素就是一个链表,jdk7之前链表中的元素采用头插法插入元素,jdk8之后采用尾插法插入元素,由于插入的元素越来越多,查找效率就变低了,所以满足某种条件时,链表会转换成红黑树。随着元素的增加,HashMap的数组会频繁扩容,如果构造时不赋予加载因子默认值,那么负载因子默认值为0.75,数组扩容的情况如下: 1:当添加某个元素后,数组的总的添加元素数大于了 数组长度 * 0.75(默认,也可自己设

zhuzhianing的博客 5万+

【数据结构】红黑树超详解 ---一篇通关红黑树原理(含源码解析+动态构建红黑树)

【数据结构】红黑树超详解 ---一篇通关红黑树底层原理(含源码解析+动态构建红黑树)

2402_84949062的博客 7772

HashMap的扩容机制

HashMap在底层数据结构上采用了数组+链表+红黑树,通过散列映射来存储键值对数据因为在查询上使用散列码(通过键生成一个数字作为数组下标,这个数字就是hash code)所以在查询上的访问速度比较快,HashMap最多允许一对键值对的Key为Null,允许多对键值对的value为Null。它是非线程安全的。在排序上面是无序的。

wming666的博客 5561

Palantir的本体论建模跟数仓建模的异同

Palantir的Foundry Ontology通过构建组织的数字孪生体,将数据集和模型映射为对象类型、属性、链接和操作类型,形成完整的语义知识网络。与传统数仓建模相比,本体建模以业务问题为驱动,强调细粒度语义和实时决策能力,采用图语义技术实现灵活的映射关系。

轩哥的个人研究和成长记录 1588

kettle多表数据迁移

点击 文件——新建——作业,在左侧的 核心对象 标签下选择 通用,双击添加一个 start ,一个 转换 ,一个 作业 和一个 成功 到右侧的作业面板,这些作业项都可以改名字。点击文件—新建—转换,在左侧的 核心对象 标签下选择 输入 下的 表输入,双击添加到右侧的转换面板,再选择 作业 下的 复制记录到结果 ,双击添加到右侧的转换面板。新建转换,在左侧的 核心对象 标签下选择 作业 下的 从结果获取记录,双击添加到右侧的转换面板,再选择 作业 下的 设置变量 ,双击添加到右侧的转换面板。

u014061745的博客 1340

HashMap扩容机制以及尾插法

1. resize定义 当HashMap中的元素越来越多的时候,碰撞的几率也就越来越高(因为数组的长度是固定的),所以为了提高查询的效率,就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,所以这是一个通用的操作,很多人对它的性能表示过怀疑,不过想想我们的“均摊”原理,就释然了,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其...

傅红雪的专栏 2万+

电路仿真软件PSIM简介

PSIM的基本使用操作...

qq_55203246的博客 7174

简述HashMap的扩容机制

resize这个方法是HashMap的扩容方法。HashMap在扩容时,都是翻两倍,比如16的容量扩大到32,。HashMap进行扩容的方法是比较巧妙的,扩容后,与原来的下标(n-1)&hash相对,其实只是多了1bit位。扩容后节点要么是在原来位置,听起来好像很懵,所以还是认真看下面的分析:下面给出例子,比如从容量为16扩容到32时,画图表示:进行扩容,扩大到原来的两倍:到这一步,下标,扩容后的数据10101和原来的00101相比,其实就是多了1bit,10101。

Nicky's blog 7015

PyQt5 使用QSqlDatabase连接Mysql数据库时Driver not loaded Driver not loaded

PyQt5 使用QSqlDatabase连接Mysql数据库时Driver not loaded Driver not loaded

睡觉不打呼噜的博客 1562

CTFshow MISC入门实战:010Editor+TweakPNG解决PNG隐写难题(附完整脚本)

本文详细介绍了在CTFshow MISC比赛中,如何利用010Editor和TweakPNG两款专业工具构建高效的PNG隐写分析工作流。文章从PNG文件结构解析入手,通过实战案例演示了如何协同使用010Editor进行二进制侦察与结构分析,以及使用TweakPNG进行数据块的精准编辑与删除,并最终提供了自动化分析脚本,帮助选手系统性地解决PNG隐写难题。

weixin_29252171的博客 74

红黑树原理简单解析

一、红黑树为什么会出现呢? 是因为二叉搜索树有可能会出现极端的情况,就是只有一侧有数据,那这样的话就会降级为链表。后来出现了平衡二叉树,但是由于强制平衡所导致付出的代价比较高昂,所以黑红树出现了。 二、简介 红黑树(Red Black Tree) 的实现是基于二叉查找树的,对于含有n个节点的二叉查找树的最坏的情况是这n个节点形成一条单链,此时二叉查找树的高度为n,时间复杂度为O(n)。为了维持O(lg n)的运行时间,就需要采取一些措施在不影响二叉查找树的性质下改变二叉查找树的结构,使之平衡。红黑树就是这样

黄沙客栈 1万+

如何利用ADS中的耦合线设计带通滤波器并转换为HFSS模型

耦合线带通滤波器是一种常用的微带滤波器形式,由多个长度为四分之一波长的耦合线节组成,在所需频点形成谐振,构成滤波器的频率响应特性。首先我们先来了解一下耦合线带通滤波器的电路结构,见下图:包括两对耦合线,中间为公共连接点,其中两对耦合线的偶奇模阻抗为(Z1e,Z1o)和(Z2e,Z2o,端口输入阻抗为Z0)。2.指定一个初始奇偶模值,ADS优化出一个合适的结果,通过奇偶模值利用linecalc工具计算出微带耦合线尺寸。假设中心频率为2GHz,则对应频点的电长度为。5.运行结果,两个软件仿真结果基本一致。

auqihc的博客 2227

红黑树

写在前面 当在10亿数据进行不到30次比较就能查找到目标时,不禁感叹编程之魅力!人类之伟大呀! —— 学红黑树有感。 终于,在学习了几天的红黑树相关的知识后,我想把我所学所想和所感分享给大家。红黑树是一种比较难的数据结构,要完全搞懂非常耗时耗力,红黑树怎么自平衡?什么时候需要左旋或右旋?插入和删除破坏了树的平衡后怎么处理?等等一连串的问题在学习前困扰着我。如果你在学习过程中也会存在我的疑问,那么本文对你会有帮助,本文帮助你全面、彻底地理解红黑树! 本文将通过图文的方式讲解红黑树的知识点,并且不会涉及到任何代

ChristinaXinny的博客 621

手把手教你用DevExpress Patch工具解决VS项目中的试用弹窗问题

本文详细指导开发者使用DevExpress Patch工具解决Visual Studio项目中恼人的试用弹窗问题。核心在于理解并分步处理:首先正确应用补丁工具以绕过运行时验证,然后重点清理或重置项目中的licenses.licx文件以消除编译时验证,从而彻底根治弹窗。

weixin_29234423的博客 588

高效与灵活相结合:Verilog编写的跨时钟域循环缓冲控制器解析

循环缓冲区,也被称作循环队列、环形缓冲区,是一种数据结构,其主要特性是使用一个固定大小的缓冲区作为数据的存储空间,这个缓冲区在逻辑上被视作是首尾相接的。虽然Verilog是一种常用的硬件描述语言,被广泛应用在FPGA和ASIC设计中,但是在描述循环缓冲区时,它并没有提供一种直接且灵活的方式来指定循环缓冲区的参数,如字长、缓冲区深度、缓冲区数量等。这给硬件设计带来了一定的不便。同时,该控制器的设计也充分考虑了硬件资源的利用率,通过优化的算法和数据结构,使得在实现高性能的同时,也能够有效地节省硬件资源。

qq_38334677的博客 1221

红黑树----原理及详细实现过程

1.红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。 2.红黑树的性质 每个节点不是红色就是黑色 根结点是黑色的 如果一个结点是红色的,则它的两个孩子是黑色的 对于每个节点,从该节点到其后代叶结点的简单路径上,均包...

lovehang99的博客 4473

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

说说HashMap的扩容机制

首先先看下HashMap几个重要的常量 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 默认初始化值16 在创建HashMap时,如果没有指定具体的值,初始化默认是16 static final int MAXIMUM_CAPACITY = 1 << 30 最大容量,即HashMap能创建的最大容量 static final float DEFAULT_LOAD_FACTOR = 0.75f; 负载因子,HashMap的

qq_37376024的博客 4366

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

hashmap 扩容机制

hashmap是一种基于数组和链表(或红黑树)的数据结构,它可以存储键值对的映射关系。hashmap的扩容机制是指当hashmap中的元素个数超过数组长度乘以负载因子时,就会重新分配一个更大的数组,并将原来的元素重新计算哈希值并插入到新的数组中。不同版本的Java实现了不同的扩容机制。

学亮编程手记 2885

【图文详解】彻底了解红黑树底层实现原理

红黑树定义 红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。 红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。 它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。(来源百度百科) 结构特点 ...

GodTheTang的博客 4704

【HashMap扩容机制】

我是廖志伟,一名Java开发工程师、幕后大佬社区创始人、Java领域优质创作者、优快云博客专家。拥有多年一线研发经验,研究过各种常见框架及中间件的底层源码,对于大型分布式、微服务、三高架构(高性能、高并发、高可用)有过实践架构经验。 博主:java_wxid 社区:幕后大佬 文章目录HashMap扩容机制 本文的大概内容: HashMap扩容机制 将(k1,v1)直接放入Node类型的数组中,这个数组初始化容量是16,默认的加载因子是0.75。 HashMap有两个参数影响其性能:初始容量和加载.

我是Java程序员廖志伟,感谢朋友们的支持! 8805

HashMap之扩容原理

一、什么是HashMap? HashMap 数据结构为 数组+链表(JDk1.7),JDK1.8中增加了红黑树,其中:链表的节点存储的是一个 Entry 对象,每个Entry 对象存储四个属性(hash,key,value,next) 二、为什么要使用HashMap? 对于要求查询次数特别多,查询效率比较高同时插入和删除的次数比较少的情况下,通常会选择ArrayList,因为它的底层是通过数组实现的。对于插入和删除次数比较多同时在查询次数不多的情况下,通常会选择LinkedList,因为它的底层是通过链

Mr_yeml的专栏 2万+

为什么红黑树查询快_目前最详细的红黑树原理分析(大量图片+过程推导!!!)...

一.为什么要有红黑树这种数据结构?我们知道ALV树是一种严格按照定义来实现的平衡二叉查找树,所以它查找的效率非常稳定,为O(log n),由于其严格按照左右子树高度差不大于1的规则,插入和删除操作中需要大量且复杂的操作来保持ALV树的平衡(左旋和右旋),因此ALV树适用于大量查询,少量插入和删除的场景中那么假设现在假设有这样一种场景:大量查询,大量插入和删除,现在使用ALV树就不太合适了,因为AL...

weixin_39971172的博客 1452

HashMap的基础概念及其扩容机制

HashMap的基础概念及其扩容机制

qq_39477236的博客 3088
上一篇: 爆肝收集来的各大厂商面试题,JVM篇:核心知识点梳理(垃圾回收算法、GC、内存泄露、对象创建等)
下一篇: MyBatis原理深入解析:优缺点、参数映射、初始化机制、Configuration对象、SqlSession、框架整体设计
SpringBoot_
博客等级 码龄8年 445粉丝 96原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值