说到HashMap,就必定要说到红黑树,红黑树做为一种自平衡二叉查找树,是一种用途较广的数据结构,在jdk1.8中使用红黑树提高HashMap的性能,今天就来讲一说红黑树,上一讲已经给出插入平衡的调整操做,这一讲就说说更为复杂的删除平衡操做。html
限于篇幅,本文只对红黑树的基础进行说明,暂不涉及源码部分,大部分摘抄自维基百科,这里也贴出对应连接:数据结构
维基百科(中文):https://zh.wikipedia.org/wiki...性能
维基百科:https://en.wikipedia.org/wiki...spa
笔者这里会根据维基百科的讲解作些说明,方便初学者理解。.net
在正式进入红黑树的删除说明以前,想下二叉搜索树中的删除是如何作的?code
参照二叉搜索树的删除调整原理:htm
若是须要删除的节点有两个儿子,那么问题能够被转化成删除另外一个只有一个儿子的节点的问题(为了表述方便,这里所指的儿子,为非叶子节点的儿子)。对于二叉查找树,在删除带有两个非叶子儿子的节点的时候,咱们要么找到它左子树中的最大元素、要么找到它右子树中的最小元素,并把它的值转移到要删除的节点中(如在这里所展现的那样)。咱们接着删除咱们从中复制出值的那个节点,它一定有少于两个非叶子的儿子。由于只是复制了一个值(没有复制颜色),不违反任何性质,这就把问题简化为如何删除最多有一个儿子的节点的问题。它不关心这个节点是最初要删除的节点仍是咱们从中复制出值的那个节点。
那么红黑树中会出现哪些状况呢?blog
对于第一种状况,咱们能够找到删除节点的后继节点,将值替换,而后删除后继节点,这样保证了该树仍然是一棵二叉树,可是在删除后继节点时可能破坏了红黑树的特性,故须要进行调整。强调一下,红黑树中的叶子节点指的都是NIL节点。递归
这样来看,被删除的节点必定有一个右子树,可能为NIL也可能为非空子树,接下来就具体看看状况。ip
1.若是删除节点E为红色,则E子节点F则必为黑色(红黑树特性),这种状况只有在E的两个节点都为叶子节点时才会发生。故删除以后红黑树平衡不用调整。能够自行画图验证:
2.若是删除节点E为黑色,F为红色,这种状况下,F节点有两个叶子节点(需保证红黑树特性,黑色路径需保持一致)则F放置到E处时只须要变色就可使得红黑树平衡
3.若是删除节点E为黑色,F也为黑色,这种状况只有在E的两个节点都为叶子节点时才会发生。参考上边状况1的验证。这里删除了一个黑色节点,红黑树平衡被破坏(黑色路径不一样了),须要进行调整
针对3这里就又会有如下几种状况:
N为删除的位置节点,如今被删除的节点的子节点取代(这里子节点对应上边的F,即删除后,N的位置为叶子节点),N为黑色,P为N的父母,S为P的右子,SL表明S的左子,SR表明S的右子。
S必不为叶子节点,反推下,若是为叶子节点,在未删除以前P的两边黑色路径就不一致了(未删除以前是P->E->F这种,自行画图理解)。注意,下面列举的状况都是在删除E节点后,子节点取代E造成的状况,在此基础上进行红黑树的调整。按照顺序每种状况进行判断处理
。注意每种状况处理以后会从新标记,以适应下次状况的对比调整,而且下列过程只以第一次调用时说明,递归调用下列顺序过程时将叶子节点当成一个已经平衡的局部红黑树便可。和以前的插入平衡调整相似,每次都是局部化调整。
第一种状况:若是N为根节点,不须要调整平衡了,原有树只有一个非叶子节点,两个叶子节点,删除了根节点,至关于删除了红黑树。继续第二种状况判断。
第二种状况:若是N(这里是叶子节点NIL)是其父P的左子节点,S为红色,P必为黑色,参照下图,反转P和S的颜色,而后在P处向左旋转,将S转换为N的祖父母。这里N处的黑色路径少一个,还未平衡。N是其父P的右子节点参照类似处理。SL标记为新的S继续以N,P,S这块局部树进行处理。继续第三种状况处理。
第三种状况:若是P,S和S的孩子都是黑色,左图显示了出现的状况,在N替换掉以前的父节点后造成的状态,这里从新绘制S为红色,变为右图,在这个局部中知足平衡红黑树的特性4和5,可是经过P节点的黑色路径相比原有结构减小了1,还须要进行调整,需从新进行平衡。这里从新平衡即从第一种状况再次顺序执行,以P节点进行从新平衡,至关于以P为新的N,黑色路径少1,再次进行平衡调整。不知足当前状况,再继续执行第4种状况处理。
第四种状况:若是S和S的孩子是黑色,但P是红色的。在这种状况下,咱们只需交换S和P的颜色。这不会影响经过S的路径上的黑色节点数量,但它确实会在经过N的路径上添加一个黑色节点数,从而弥补这些路径上已删除的黑色节点。将达到红黑树平衡。不知足当前状况,则继续第五种状况的处理。
第五种状况:若是S是黑色,S的左孩子是红色,S的右孩子是黑色,N是其父母的左孩子。在这种状况下,咱们在S处右转,这样S的左边孩子就成了S的父母和N的新兄弟。而后咱们交换S及其新父母的颜色。全部路径仍然有相同数量的黑色结点,可是P的左子树由于删除一个节点致使黑色路径少1,还未彻底平衡。这里进行调整主要是为了知足第六种状况,继续第六种状况的处理。
第六种状况: 若是S是黑色,S的右子是红色,N是其父P的左子。在这种状况下,咱们向左旋转P,这样S成为P和S的右子的父亲。而后,咱们交换P和S的颜色,并使S的右子节点变黑。比较删除前与N替换调整后的属性,知足4和5,与删除前是一致的。
删除操做相对插入操做以后的平衡要复杂的多,不过按照状况一步步处理也是比较明了的,一样为了方便初学者理解,从上边的过程咱们也能够发现,在一次局部平衡调整中,最多进行3次旋转操做,我这里再进行一个流程梳理,帮助各位更好的理解红黑树的删除操做。
到此关于红黑树的基础已经介绍完毕,下一章我将就JDK源码中的TreeNode进行讲解说明,看一看红黑树是如何在源码中实现的。
参考资料: