红黑树删除之向上调整

bug

从图来看,向上调整了一层,2的父结点4也做了调整。

删除0

正确的删除

正确删除0后应该是这样的。 [0, 17, 16, 10, 11, 12, 1, 21, 18, 4, 19, 8, 14, 3, 2, 7, 20, 15, 13, 9, 6, 5]22个随机数构成的红黑树删除0。

删除0后

错误的删除

调试代码时错误的情况。2作为1的左子树上也不符合二叉查找树的要求。

删除0错误的情况

删除之前

删除之前

0是黑色结点,删除后会破坏红黑树的平衡。是情形3:兄弟w为黑色,且其孩子左红右空。调整后转成情形4再调整一次就恢复平衡,不用再向上调整。正好是红黑树的删除图例的情形3。

情形四修正

#4.w为黑色,且其孩子左黑右红或左红右红。调试代码是这里出了问题。黑有时也是空的意思。要添加左空右红的情况。

原代码

if w and ((w.left and w.left.color == BLACK and w.right and w.right.color == RED )

改正后

镜像的代码也对应修改。

if w and (((w.left == None or w.left and w.left.color == BLACK )and w.right and w.right.color == RED )

用例

a = [0, 17, 16, 10, 11, 12, 1, 21, 18, 4, 19, 8, 14, 3, 2, 7, 20, 15, 13, 9, 6, 5]

22个数据递增和递减构造的图都是7层,随机数据构造的图是6层。

#22递增的图,递减的图都是7层,随机图6层,
#for v in range(22):
#for v in range(21,-1,-1): #22递增的图
#a = [i for i in range(22)]
#random.shuffle(a)
#print(a)
a = [0, 17, 16, 10, 11, 12, 1, 21, 18, 4, 19, 8, 14, 3, 2, 7, 20, 15, 13, 9, 6, 5]
for v in a:
    rb.INSERT(v)  

本来想看看删除递归向上调整的情况,一删除0,代码就有问题了。画出图形,用随机数测试还是很有帮助的。

删除1

从前面第一张图"删除0后"可以看出,此时删除1是情形2:兄弟w为黑色,且其孩子为空 。需要向上调整,是怎么调整的呢?

这一删问题更大了,还有好多bug,这里略去了很多图。具体参照红黑树的删除修改。

主要修改

  • 1、 反色。要判断之前颜色再设置新颜色。
py 复制代码
                if w.left.color == RED:
                    w.left.PAINT(BLACK)
                else:
                    w.left.PAINT(RED)
  • 2、置 w 与 x . p w与 x. p w与x.p同色。 之前试的例子太少,自以为是地写成了黑色。
  • 3、黑有时是表示NIL结点。

修改前

py 复制代码
        #2.w为黑色或空,且其孩子左黑右黑        
        if w == None or (w.left and w.left.color == BLACK and w.right and w.right.color == BLACK)or(w.left is None and w.right is None):
            if w:w.PAINT(RED)
            if p.parent:            
                p.PAINT(BLACK)
                if p == p.left:
                    w = p.right
                    p = p.parent
                else:
                    w = p.right
                    p = p.parent
                self.DELETE_FIXUP(p,w) 


        #4.w为黑色,且其孩子左黑右红或左红右红
        if w and (((w.left == None or w.left and w.left.color == BLACK ) and w.right and w.right.color == RED )
            or (w.left and w.left.color == RED and w.right and w.right.color == RED)):
            p.PAINT(BLACK)
            if w == p.right:
                self.LEFT_ROTATE(p)
                w.right.PAINT(BLACK)
            elif w == p.left:
                self.RIGHT_ROTATE(p)
                w.left.PAINT(BLACK)
        #镜像情况                
        elif w and (((w.right == None or w.right and w.right.color == BLACK ) and w.left and w.left.color == RED )
            or (w.right and w.right.color == RED and w.left and w.left.color == RED)):
            p.PAINT(BLACK)
            if w == p.left:
                self.RIGHT_ROTATE(p)
                w.left.PAINT(BLACK)
            elif w == p.right:
                self.LEFT_ROTATE(p)
                w.right.PAINT(BLACK) 

修改后

py 复制代码
        #2.w为黑色或空,且其孩子左黑右黑        
        if w == None or (w.left and w.left.color == BLACK and w.right and w.right.color == BLACK)or(w.left is None and w.right is None):
            if w:w.PAINT(RED)
            if p.parent:            
                if p == p.parent.left:
                    w = p.parent.right
                    p = p.parent
                else:
                    w = p.parent.right
                    p = p.parent
                self.DELETE_FIXUP(p,w)
        #3.w为黑色,且其孩子左红右黑
        if w and w.left and w.left.color == RED and (w.right == None or w.right and w.right.color == BLACK):
            w.left.PAINT(BLACK)
            w.PAINT(RED)
            self.RIGHT_ROTATE(w)
            w = p.right
        #镜像情况
        elif w and w.right and w.right.color == RED and (w.left == None or w.left and w.left.color == BLACK):
            w.right.PAINT(BLACK)
            w.PAINT(RED)
            self.LEFT_ROTATE(w)
            w = p.left 
        #4.w为黑色,且其孩子左黑右红或左红右红
        if w and (((w.left == None or w.left and w.left.color == BLACK ) and w.right and w.right.color == RED )
            or (w.left and w.left.color == RED and w.right and w.right.color == RED)):
            w.PAINT(p.color)
            p.PAINT(BLACK)
            if w == p.right:
                self.LEFT_ROTATE(p)
                if w.right.color == RED:
                    w.right.PAINT(BLACK)
                else:
                    w.right.PAINT(RED)
            elif w == p.left:
                self.RIGHT_ROTATE(p)
                if w.left.color == RED:
                    w.left.PAINT(BLACK)
                else:
                    w.left.PAINT(RED)
        #镜像情况                
        elif w and (((w.right == None or w.right and w.right.color == BLACK ) and w.left and w.left.color == RED )
            or (w.right and w.right.color == RED and w.left and w.left.color == RED)):
            w.PAINT(p.color)
            p.PAINT(BLACK)
            if w == p.left:
                self.RIGHT_ROTATE(p)
                if w.left.color == RED:
                    w.left.PAINT(BLACK)
                else:
                    w.left.PAINT(RED)
            elif w == p.right:
                self.LEFT_ROTATE(p)
                if w.right.color == RED:
                    w.right.PAINT(BLACK)
                else:
                    w.right.PAINT(RED)  

还是错

删除调整修正后删除1的图

3在2的左支,不符合红黑树,也不符合二叉排序树。

调试

不应该啊,已接近崩溃,又做了如下测试。

rb.DELETE(1)
rb.draw(rb.root)

rb.root.left.left.left.left.val
Traceback (most recent call last):
  File "<pyshell#47>", line 1, in <module>
    rb.root.left.left.left.left.val
AttributeError: 'NoneType' object has no attribute 'val'
rb.root.left.left.left.right.val
3

2的左支没有3,它在右支。不会是画图代码有问题吧!加个search方法直接定位结点,这就是后话了。

修正

之前编码时,先写的只有左支的情况,是入队左和NIL。再抄到只有右支的情况,写成了先入队右再入队NIL。

py 复制代码
            elif q.right:
                temp.append(RBTnode(-1))
                temp.append(q.right)
                endlevel = level + 1
#之前写的是:
            elif q.right:
                temp.append(q.right)
                temp.append(RBTnode(-1))
                endlevel = level + 1
代码里还有错吗?

从图来看,向上调整了一层,2的父结点4也做了调整。也许一直向上调整的情况没有那么容易碰到。调试情况如下:

DELETE_FIXUP只嵌套调用了一次

重点

失业了,求职中!能有口饭吃将不胜感激。

相关推荐
何大春1 分钟前
【弱监督语义分割】Self-supervised Image-specific Prototype Exploration for WSSS 论文阅读
论文阅读·人工智能·python·深度学习·论文笔记·原型模式
在下不上天9 分钟前
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
大数据·开发语言·python
SEVEN-YEARS13 分钟前
深入理解TensorFlow中的形状处理函数
人工智能·python·tensorflow
EterNity_TiMe_17 分钟前
【论文复现】(CLIP)文本也能和图像配对
python·学习·算法·性能优化·数据分析·clip
Suyuoa29 分钟前
附录2-pytorch yolov5目标检测
python·深度学习·yolo
好看资源平台2 小时前
网络爬虫——综合实战项目:多平台房源信息采集与分析系统
爬虫·python
进击的六角龙2 小时前
深入浅出:使用Python调用API实现智能天气预报
开发语言·python
檀越剑指大厂2 小时前
【Python系列】浅析 Python 中的字典更新与应用场景
开发语言·python
湫ccc2 小时前
Python简介以及解释器安装(保姆级教学)
开发语言·python
孤独且没人爱的纸鹤2 小时前
【深度学习】:从人工神经网络的基础原理到循环神经网络的先进技术,跨越智能算法的关键发展阶段及其未来趋势,探索技术进步与应用挑战
人工智能·python·深度学习·机器学习·ai