其他分享
首页 > 其他分享> > 红黑树(下)

红黑树(下)

作者:互联网

红黑树具有以下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必定是黑色节点,子节点必定是红色节点,否则就不符合红黑树的性质了。那么调整策略如下:

第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颜色的不同,调整策略也不同:

az是左节点

 

az是右节点

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节点位置的不同,调整策略也不同:

az是左节点

az是右节点

az是左节点

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

az是右节点

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

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

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

 

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

 

 

 

 

 

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

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

 

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

 

 

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

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

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

 

 

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

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

 

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

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

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