from turtle import *
class BinaryTree:
    def __init__(self,rootObj):#接受的参数是它本身和根节点两个参数
        self.key = rootObj
        self.leftChild = None #此时左子树和右子树都为空
        self.rightChild = None
    #插入左子节点
    def insertLeft(self,newNode):
        if self.leftChild == None: #如果原本没有左子节点,此时只需要往树中添加一个节点,如果已经存在左子节点,则插入一个节点,把原来的节点降一层
            self.leftChild = BinaryTree(newNode)
        else:
            t = BinaryTree(newNode)
            t.left = self.leftChild
            self.leftChild = t
    def insertRight(self, newNode):
        if self.rightChild == None:  # 如果原本没有左子节点,此时只需要往树中添加一个节点,如果已经存在左子节点,则插入一个节点,把原来的节点降一层
            self.rightChild = BinaryTree(newNode)
        else:
            t = BinaryTree(newNode)
            t.left = self.rightChild
            self.rightChild = t
    def getrightChild(self):
        return self.rightChild
    def getleftChild(self):
        return self.leftChild
    def setRootVal(self,obj):
        self.key = obj
    def getRootVal(self):
        return self.key
    def getatree():
         t = BinaryTree(0)
         t.leftChild=BinaryTree(1)
         t.rightChild=BinaryTree(2)
         temp = t.getleftChild()
         temp.leftChild = BinaryTree(3)
         temp.rightChild = BinaryTree(4)
         temp=t.getrightChild()
         temp.leftChild=BinaryTree(5)
         temp.rightChild=BinaryTree(6)
         return t

首先是二叉树的数据结构的定义,以及定义了一个getatree方法来快速获得一个二叉树。

下面我们来考虑绘制一个二叉树,首先,绘制一个二叉树也要把里面的元素写在旁边,在这里我们选择调用Turtle中的write()方法,其定义如下:

turtle.write(s [,font=("font-name",font_size,"font_type")])

 其中,为文本内容,font是字体的参数,分别为字体名称,大小和类型;font为可选项,font参数也是可选项,在这里我们需要写出的是这一节点的元素,也就是说一个根节点的内容。到后面和绘制分形树类似使用了递归,这个时候,第一个根节点的子节点就是后面的树的根节点,首先第一次访问的则是整个二叉树的根节点0.

def drawTree(mt,tree,Len,Arg):#接受两个参数,分别是树干的长度和角度
    mt.write(tree.key)

下面我们先绘制左子树,绘制左子树的条件是左子树不能为空。

if tree.leftChild:
        p = mt.pos()
        mt.right(Arg)
        mt.fd(Len)
        mt.left(Arg)
        drawTree(mt,tree.leftChild,Len*0.8,Arg*0.8)
        mt.up()
        mt.goto(p)
        mt.down()

在这里采用和绘制分形树类似的思想,首先要绘制左边的树(我们看到的左边),对Turtle来讲应该想右侧转Arg度,然后再转回来转到正方向上,接着就进入了递归,如果这个左子节点还有左子节点,继续如上让他转Arg度,往前跑Len*0.8,此时如果这个节点没有左子树了,就回到相对其现在节点的一层的根节点,然后就要绘制这个根节点的右子树了,定义如下:

if tree.rightChild:
        p=mt.pos()
        mt.left(Arg)
        mt.fd(Len)
        mt.right(Arg)
        drawTree(mt,tree.rightChild,Len*0.8,Arg*0.8)
        mt.up()
        mt.goto(p)
        mt.down()

用IDLE进行测试:

t = Turtle()
m=BinaryTree.getatree()
drawTree(t,m,100,60)

结果:

二叉树绘制python代码_算法

在这里补充一下类似的分形树的想法:

从之前的谢尔宾斯基三角形我们可以看出,这些递归程序都会先一直完成某一个部分直到不能继续,比如谢尔宾斯基三角形最开始一直在绘制左下角的三角形,直到左下角完全绘制完成再转过来去绘制其他部分,分形树也是如此,要绘制一棵树,我们首先要确定它的枝干的长度,以及其一条树干上的小树枝之间的角度,也就是说要确定两个变量。

一开始我们先绘制出最长的树干(A)(这很简单,只需要一个fd()),然后绘制其上的小树干(B,C),不妨定义成比这个树干短五个像素,和这个树干的夹角为20度,此时我们又绘制出了一条树干,对于它上面的小树枝(1,2...),B与(1,2...)之间的关系就和A与B的关系是一样的,和谢尔宾斯基三角形一样,他们都是由无数个类似的小基本单位组成的,因此可以使用递归,一直画到最小的单位。

from turtle import *
t=Turtle()
mywin = t.getscreen()
t.speed(1)
def draw(len,t):
    if len>10:
        t.forward(len)
        t.right(20)
        draw(len-15,t)
        t.left(40)
        draw(len-10,t)
        t.right(20)
        t.backward(len)
draw(50,t)
mywin.exitonclick()

左转四十度的原因和上面右转Arg的原因类似,