红黑视觉化

不堪回首

第一篇前就想画了,没有底气只能说打印。曾经手画过,也显示了更紧凑的234B树,还盗过图。“直男”应该是女程序员给她男朋友取的,她知道他的心底压满了栈,只能直进直出;也期待着出栈的欣喜。

0到49插入的红黑树0到49插入的红黑树

略显粗糙

最美公式

log ⁡ 2 n \log_{2}{n} log2n

log ⁡ 2 n \log_{2}{n} log2n是完全二叉树的层数,其中 n n n是接点数;只有一个结点的根结点是0层。书上原话:**性质4具有 n n n个结点的完全二叉树的高度 k k k ⌊ log ⁡ 2 n ⌋ ⌊\log_{2}{n} ⌋ log2n。⌊ ⌋向下取整。**从上图可以看出,画图的代码里构造了完全二叉树,用count += 1 #计数得到公式中的 n n n,从而求出层数。再用层数计算 x , y x,y x,y坐标。

>>> import math
>>> math.log(1,2)
0.0
>>> 

2 n 2^n 2n

每层的结点数。代码 s t e p = ( 1 / 2 ) ∗ ( ( 1 / 2 ) ∗ ∗ l e v e l ) ∗ 1500 step = (1/2)*((1/2)**level) * 1500 step=(1/2)((1/2)level)1500 #用结点数计算 x x x的间隔 s t e p step step,根是 1 2 \frac{1}{2} 21的宽度,下一层就再乘以一个 1 2 \frac{1}{2} 21。x =(count - 2**level)step2 + step 便求出了x坐标。

NIL节点(空叶子节点)为黑色

红黑树性质里都有说这个NIL结点。之前以为没有用。这次画图用到了,它是画图结束的关键,红黑树远远不是完全二叉树。只要有NIL结点就还要往下画一层。endlevel = 1 #null层,添加一个变量作为最后层的标志。

准备工作

海龟可以画直线和圆,显示数字;结点类可以添加xy坐标,树类可以添加层、接点数量属性,还可以结合后根序倒推。还有很多失败的过程,要追求的是逻辑编程的简洁。

不用担心本子不够画了

	from turtle import *
	import math
    def draw(self, node):#不用担心本子不够画了
        if node is None: return
        setup(width=1600, height=900) #画布大小
        setworldcoordinates(-50, -850, 1550, 50) #50像素页眉
        speed("fastest")#最快
        temp = [] #队列先进先出
        temp.append(node)#入队 
        step = 1/2 #根结点居中 
        x,y = 0,0 #结点坐标
        count = 0 #结点计数,完全二叉树
        level = 0 #层数
        endlevel = 1 #nul层,最后层
        split = True #重在一起的处理
        while temp:
            q=temp.pop(0)#出队
            count += 1 #计数
            level = int(math.log(count,2)) #当前层
            y = 0 - 50 * level #y下降
            step = (1/2)**(level+1) * 1500 #x的间隔step
            if count == 2**level:
                x = step
            else:
                x =(count - 2**level)*step*2 + step
            if step < 10:#重在一起处理
                if split:
                    goto(x-3,y)
                    split = False
                else:
                    goto(x+3,y)
                    split = True
            else:
                goto(x,y)
            color(q.color) #着色                
            if q.val != -1: #nul接点不显示 
                write(q.val, font=("微软雅黑", 10, "normal"))
            color('black') #着色完恢复
            if q.left and q.right: #下一层
                temp.append(q.left)
                temp.append(q.right)
                endlevel = level + 1 #nul层,最后层要增加
            elif q.left:
                temp.append(q.left)
                temp.append(RBTnode(-1))
                endlevel = level + 1
            elif q.right:
                temp.append(q.right)
                temp.append(RBTnode(-1))
                endlevel = level + 1
            elif endlevel >= level:
                temp.append(RBTnode(-1))
                temp.append(RBTnode(-1))
        getcanvas().postscript(file="filename.ps")#保存图片
               

说明

  1. 在还有子结点的情况下,endlevel = level + 1表示还有一层nil.
  2. 只画一层nil,即没有子结点但endlevel >= level的时候也入队RBTnode(-1)。再一层的时候当前层level会大于没有+1的endlevel。
  3. RBTnode(-1),在空的地方添加,以构造完全二叉树。画图的时候(-1)就不显示。

只能到九层了

第八层就重叠了,还特殊处理了才行。还好,可以从任意结点开始画。

从任意结点画

从31开始画:

>>> rb.draw(rb.root.right.right)
在这里插入图片描述‘31’开始画的红黑树

观止

所见即所得

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值