ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

红黑树(下)

2021-04-30 02:33:46  阅读:290  来源: 互联网

标签:黑色 删除 双黑 红色 红黑树 az 节点


红黑树具有以下5条性质:

  1. 树中的节点要么是红色要么是黑色
  2. 根节点是黑色
  3. 每一个叶子节点(Nil,空节点,实际不存储数据)都是黑色的
  4. 红色节点的两个孩子都是黑色的
  5. 对于每一个节点,从它出发到它的后代叶子节点的所有简单路径上,黑色节点的数量都是相同的

我们在向红黑树插入新节点的时候,因为要保证红黑树的性质,会通过变色或者旋转来调整节点。那么删除红黑树的节点,我们会碰到什么情况呢?

红黑树的删除操作

红黑树是一棵二叉排序树,所以红黑树的删除过程和二叉排序树的删除过程一样。在二叉树排序树的删除过程中,假设我们要删除的节点是Z,如果Z没有孩子,直接删除就行,否则需要找到Z的中序遍历前驱或后继顶替它的位置。不过删除节点后,可能会破坏红黑树的性质,我们需要调整策略来维持红黑树的性质。

举一个最简单的例子,az是要删除的节点,我们删除节点az之后,需要找到az的后继节点Z来顶替az的位置,颜色变成az一样,然后Z的孩子节点需要补位Z所在的位置,整个过程就相当于az保持不变,把az的后继节点Z删除一样。这里的az是有左右2个非Nil子节点的情况,az也存在只有一个非空子节点或者没有非空子节点的情况,所以我们需要根据az的不同情况来调整。

第1种情况:az有1个非Nil子节点

az有1个非Nil子节点的时候,那么az必定是黑色节点,子节点必定是红色节点,否则就不符合红黑树的性质了。那么调整策略如下:

  • 1.1 红色子节点是左节点,删除az节点,A节点顶替az的位置,变成和az一样的颜色

  • 1.2 红色子节点是右节点,删除az节点,A节点顶替az的位置,变成和az一样的颜色

第2种情况:az有0个非Nil子节点

az有0个非Nil子节点的时候,那么az可能是黑色节点,也可能是红色节点,我们分情况来讨论:

2.1 az是红色节点,直接删除az节点,不影响红黑树性质

az是红色节点,不管az是父节点的左节点或者右节点,那么父节点A一定是黑色节点,子树a可能是Nil节点,也可能是红色节点,不过调整策略都是一样的,直接删除az节点就可以了

az是左节点

 

az是右节点

2.2 az是黑色节点,az的兄弟节点W是黑色,W的两个儿子也是黑色

根据az父节点A颜色的不同,调整策略也不同:

  • 2.2.1 az的父节点A是红色,不管az是左节点还是右节点,直接删除az,把节点W变成红色,节点A变成黑色

az是左节点

 

az是右节点

  • 2.2.2 az的父节点A是黑色

az是父节点A的左节点,删除az节点,节点A的左子树路径上少了一个黑色节点,这里我们引入双黑节点,我们可以让顶替的黑色节点a暂时承担双黑的节点,这样左子树路径上黑色节点数不变。我们需要想办法把双黑节点变成单黑节点,把节点W变成红色,这样就消掉了节点a的一个黑色,但是节点A的这棵子树上的黑色节点数少了,所以为了维持节点A所在子树的黑色节点数,我们暂时把节点A变成双黑节点,类似于双黑节点a,我们可以采用双黑节点a相同的策略2.2、2.3、2.4、2.5、2.6,依次往上调整

az是左节点

az是父节点A的右节点的情况是类似的

2.3 az是黑色节点,az的兄弟节点W是黑色,W的两个儿子也是红色

根据az父节点A颜色和az节点位置的不同,调整策略也不同:

  • 2.3.1 az的父节点A是红色,az是左节点,删除az,az的子节点a变成双黑节点,对节点A进行左旋,然后节点W和节点A的颜色互换,最后节点w2由红色变成黑色,消掉节点a的一个黑色

az是左节点

  • 2.3.2 az的父节点A是红色,az是右节点,删除az,az的子节点a变成双黑节点,对节点A进行右旋,然后节点W和节点A的颜色互换,最后节点w1由红色变成黑色,消掉节点a的一个黑色

az是右节点

  • 2.3.3 az的父节点A是黑色,az是左节点,删除az,az的子节点a变成双黑节点,对节点A进行左旋,然后节点W和节点A的颜色互换,最后节点w2由红色变成黑色,消掉节点a的一个黑色

az是左节点

会发现,其实和2.3.1是类似的

  • 2.3.4 az的父节点A是黑色,az是右节点,删除az,az的子节点a变成双黑节点,对节点A进行右旋,然后节点W和节点A的颜色互换,最后节点w1由红色变成黑色,消掉节点a的一个黑色

az是右节点

会发现,其实和2.3.2是类似的

2.4 az是黑色节点,az的兄弟节点W是黑色,W的左儿子是黑色,右儿子是红色

根据az父节点A颜色和az节点位置的不同,调整策略也不同:

  • 2.4.1 az的父节点A是红色,az是左节点,删除az,az的子节点a变成双黑节点,对节点A进行左旋,然后节点W和节点A的颜色互换,最后节点w2由红色变成黑色,消掉节点a的一个黑色

 

会发现,其实和2.3.1是类似的,只要W的右儿子是红色,左儿子是红色或者黑色,调整策略都是类似的

  • 2.4.2 az的父节点A是红色,az是右节点,删除az,az的子节点a变成双黑节点,对节点W进行左旋,然后节点w2和节点W的颜色互换,再使用类似2.3.2的调整策略就可以了

 

 

 

  • 2.4.3 az的父节点A是黑色,az是左节点,删除az,az的子节点a变成双黑节点,对节点A进行左旋,然后节点W和节点A的颜色互换,最后节点w2由红色变成黑色,消掉节点a的一个黑色

 

  • 2.4.4 az的父节点A是黑色,az是右节点,删除az,az的子节点a变成双黑节点,对节点W进行左旋,然后节点w2和节点W的颜色互换,再使用类似2.3.4的调整策略就可以了

 

2.5 az是黑色节点,az的兄弟节点W是黑色,W的左儿子是红色,右儿子是黑色

根据az父节点A颜色和az节点位置的不同,调整策略也不同:

  • 2.5.1 az的父节点A是红色,az是左节点,删除az,az的子节点a变成双黑节点,对节点W进行右旋,然后节点w1和节点W的颜色互换,再使用类似2.3.1的调整策略就可以了

  • 2.5.2 az的父节点A是红色,az是右节点,删除az,az的子节点a变成双黑节点,对节点A进行右旋,然后节点W和节点A的颜色互换,最后节点w1由红色变成黑色,消掉节点a的一个黑色

 

会发现,其实和2.3.2是类似的,只要W的左儿子是红色,右儿子是红色或者黑色,调整策略都是类似的

  • 2.5.3 az的父节点A是黑色,az是左节点,删除az,az的子节点a变成双黑节点,对节点W进行右旋,然后节点w1和节点W的颜色互换,再使用类似2.3.3的调整策略就可以了

 

  • 2.5.4 az的父节点A是黑色,az是右节点,删除az,az的子节点a变成双黑节点,对节点A进行右旋,然后节点W和节点A的颜色互换,最后节点w1由红色变成黑色,消掉节点a的一个黑色

 

会发现,其实和2.3.4是类似的,只要W的左儿子是红色,右儿子是红色或者黑色,调整策略都是类似的

2.6 az是黑色节点,az的兄弟节点W是红色

az是黑色节点,兄弟节点W是红色节点,不管W是父节点的左节点或者右节点,那么父节点A一定是黑色节点,子树a、b、c、d可能是Nil节点,也可能是红色节点,不过调整策略都是一样的,根据az节点位置的不同:

  • 2.6.1 az的父节点是黑色,az是左节点,删除az,az的子节点x变成双黑节点,对节点A进行左旋,然后节点A和节点W的颜色互换,发现x的父节点A是红色,x的兄弟节点是黑色,那么x可以使用2.2.1、2.3.1、2.4.1、2.5.1的策略来调整

 

  • 2.6.2 az的父节点是黑色,az是右节点,删除az,az的子节点x变成双黑节点,对节点A进行左旋,然后节点A和节点W的颜色互换,发现x的父节点A是红色,x的兄弟节点是黑色,那么x可以使用2.2.1、2.3.2、2.4.2、2.5.2的策略来调整

 

第3种情况:az有2个非Nil子节点

az有2个非Nil子节点,那么右子树a2必定存在az的后继节点A,删除az,用A顶替az,然后节点A的孩子节点补位节点A的位置,根据节点A的非Nil孩子节点情况:

  • 3.1 节点A没有非Nil孩子节点,节点A顶替az的位置,Nil孩子节点x补位节点A,相当于删除节点A,如果节点A是红色,不需要调整,不影响红黑树性质,如果是黑色,对应第2种情况

  • 3.2 节点A只有1个非Nil孩子节点,节点A顶替az的位置,非Nil孩子节点y补位节点A,相当于删除节点A,子节点y染成节点A相同的颜色即可

 

不存在节点A有2个非Nil孩子节点的情况,如果存在,那么节点A就不是节点az的后继节点

 红黑树的删除操作实现代码,可以参考 https://gitee.com/liuanyou/redblacktree

标签:黑色,删除,双黑,红色,红黑树,az,节点
来源: https://www.cnblogs.com/junior-liu-learn-programming/p/14651447.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有