红黑树删除的步骤:
- 找到要删除的节点
- 删除节点
- 判断是否需要修正
红黑树的定义:
- 根节点是黑色的
- 每个节点要么是黑色的要么是红色的
- 不能出现同时为红色的父子节点
- 每个节点到它的叶子节点的所有路径上所经过的黑色节点的数量必须要保持一致
仔细想一下,如果删除了一个节点,最有可能打破的是条件1、3、4。因为:1.如果删除的是根节点,而根节点的孩子节点有可能是红色的,删除根节点后,它的孩子节点替代根节点,此时根节点就是红色的。3.如果删除一个黑色节点,这个黑色节点有红色的父亲节点和红色的孩子节点,那么如果删除掉这个黑色节点后,它的红色父亲节点和红色 孩子节点就有可能相遇。4,其实这个条件是最容易遇到的,因为如果删除一个黑色节点的话,那么经过这个黑色节点到叶子节点的路上所经过的黑色节点数量必定就减少1。
其实,如果仔细看上面这三种情况,就会发现,如果删除的是一个黑色节点,那么久必定需要修正的,而如果是删除的是一个红色节点,那么就不用向那么多了,因为如果删除的是一个黑色节点,那么条件4不影响,而且,如果是红色节点,那么他的父亲和孩子节点就不可能是红色的,也不会影响到条件3和1。
删除红黑树节点也是和删除平衡树节点的情况差不多(多一个删除修正),其具体情况有以下几种:
- 删除节点只有一个孩子:(直接删除此节点,然后将孩子节点代替父亲节点)
- 删除节点没有孩子:(直接删除节点)
- 删除节点有两个孩子:(找到这个节点的后继节点,然后将后继节点代替这个节点)
以上是删除树节点的三种情况,如果考虑平衡修正的话:
- 删除节点只有一个孩子:如果删除的节点是红色的,直接删除就行,不会影响平衡;如果删除节点是黑色的,那么就要考 虑孩子节点了(只有一个孩子节点,考虑红黑树平衡条件,这个孩子节点肯定是红色的,不然左右 孩子不平衡),所以,直接将孩子节点代替父亲节点后,将这这个节点染黑
- 删除节点没有孩子:如果删除的节点是红色的,那么直接删除,平衡不受影响,如果删除的节点是黑色的,那么平衡表就 此打破,赶紧想办法平衡吧。
- 删除节点有两个孩子节点:找到此节点的后继节点,然后将孩子节点的值覆盖要删除的节点的值,然后删除后继节点。 这 样问题就转变成考虑后继节点处是否平衡了。而这个要删除节点有两个孩子,那么,后继节点就一定 是它的右孩子节点中最左边的节点了。这种情况下,后继节点不可能有两个孩子,也就是说后继节点 要么只有一个右孩子,要么没有孩子,而这两种情况又刚好是以上讨论的两种情况。
综上所述,其实主要还是情况2,情况1很好修正,直接染黑孩子节点就行了,而情况3最终还是转换为情况1和情况2
注意:删除修正的核心思想是从别的 地方借一个红色节点过来拟补上丢失的黑色节点,或者将根节点变成红色的,然后染黑根节点。
所以:我们主要考虑情况2:
Case 1:被删除节点是黑色的,它的兄弟节点是红色的(父亲节点是黑色的)。(交换兄弟和父亲节点的颜色,然后左旋转父亲节 点,重新设置兄弟节点)
Case 2: 被删除节点是黑色的,它的兄弟节点是黑色的(父亲节点不确定),并且,它的孩子都是黑色的(染红兄弟节点,然后将父 亲节点设成当前节点,继续处理)
Case 3: 被删除节点是黑色的,它的兄弟节点是黑色的,它的左孩子是红色的,右孩子是黑的(染红兄弟节点,染黑兄弟的左孩 子节点,以兄弟节点为支点进行右旋转,重新设置兄弟节点)
Case 4: 被删除节点是黑色的,它的兄弟节点是黑色的,它的右孩子是红色的,左孩子随意(交换父亲和兄弟节点的颜色 ,染 黑 兄弟节点的右孩子然后以父亲节点为支点进行左旋转)
具体分析:
Case 1:如果被删除节点的兄弟节点是红色的(父亲节点必定是黑色的),那么其实可以从他那里借一个红色节点过来拟补丢失 的黑色节点的。具体处理就是染黑兄弟节点,然后以父亲节点左旋转,此时被删除节点这一支就拟补上删除的黑色节 点了,但是要注意一点:兄弟节点是红色的,然后被删除节点是黑色的,那么,兄弟节点就一定是两个非空的孩子的 ,而且,这两个孩子或者孩子的孩子中一定有一个黑色节点的,当父亲节点左旋转后,父亲节点的孩子节点中黑孩子个 数还是不平衡的(父亲节点的右孩子黑色节点数比左边多1)。这需要继续平衡。
Case 2:如果被删除节点有一个黑色兄弟,并且兄弟节点有两个黑色的孩子(这两个孩子一定是空节点)。这种情况就是:被删除 节点和兄弟节点都是黑色的,而父亲节点就不能确定了。此时就不能向兄弟以及他的孩子节点中去借了。而我们可以根 据删除节点修复的核心思想:从别处借,或者染黑根节点;那么这种情况下,我们可以同时染红要被删除的节点和它的 兄弟节点(这样父亲节点的左右孩子中黑色节点数量一致了,但是经过父亲节点到叶子节点的路径上黑色节点就少一个 了,这种情况就很像是我们删除节点后,根据被删除节点颜色判断平衡的情况,此时我们也可以将父亲节点当成当前节 点来判断)最后将父亲节点当成当前节点继续处理。
Case 3:如果被删除节点的兄弟节点是黑色的,兄弟节点的左孩子是红色的,右孩子是黑色的(右孩子是空的)。这种情况很简单, 我删除黑色节点,黑色节点数量少1了,而兄弟节点的孩子中不是刚好有红色节点嘛,我们借过来染黑不就行了嘛,具 体操作就是:交换兄弟节点和它的左孩子节点的颜色,然后以兄弟节点为支点进行右旋转,这种情况就刚好是Case 4:
Case 4:如果被删除节点是黑色的,兄弟节点也是黑色的,并且,兄弟节点的右孩子是红色的,左孩子随意:那么,还是一样 的,借红色节点过来,然后染黑。具体操作就是:染黑兄弟节点的右孩子,交换兄弟节点和父亲节点的颜色,然后以父 亲节点为支点进行左旋转此时就平衡了。
如果发现有问题或者疑惑请留言