我的目标是用python乌龟绘制一个二叉树,在这个意义上每条线分成2个,每个分支分成另外两个,等从左到右,看起来像{{0除了从左到右水平。这是我迄今为止所拥有的,并且它有效,但如果你运行它,你很快就会意识到它在很多方面都搞砸了。
def tree(d,x1,y1):
#d is the depth
if d==0: #base case
return 0
a = t.Turtle()
b = t.Turtle()
t.penup()
a.goto(x1,y1)
b.goto(x1,y1) # move to the correct position
t.pendown()
a.left(30)
b.right(30)
a.forward(50)
b.forward(50)
ax,ay = a.pos() #get position of new turtles
bx,by = b.pos()
input() # Debug ( PRESS ENTER FOR EACH LOOP)
tree(d-1,ax,ay) #recurse top branch
tree(d-1,bx,by) #recurse bottom branch
tree(3,0,0)
有人可以告诉我什么是错的,也许可以解决这个问题?我可以说角度需要改变,但我不知道该怎么做。
答案 0 :(得分:1)
据我所见:
您应该在海龟实例penup()
和pendown()
上调用a
和b
,而不是模块上。这将解决goto
上的可见行。
如果您在每个深度级别固定长度和角度,则在第二级别上您将开始叠加节点。级别n上两个节点之间的垂直距离应大于级别n + 1上的距离,以确保在较低级别没有重叠的节点(或边缘)。请注意,级别n + 1上两个节点的垂直距离为2*forward(n)*sin(angle(n))
。
像
这样的东西def tree(d,x1,y1):
#d is the depth
if d==0: #base case
return 0
a = t.Turtle()
b = t.Turtle()
a.penup()
b.penup()
a.goto(x1,y1)
b.goto(x1,y1) # move to the correct position
a.pendown()
b.pendown()
a.left(45)
b.right(45)
a.forward(10*(2**d))
b.forward(10*(2**d))
ax,ay = a.pos() #get position of new turtles
bx,by = b.pos()
tree(d-1,ax,ay) #recurse top branch
tree(d-1,bx,by) #recurse bottom branch
应该有用。
答案 1 :(得分:1)
我的解决方案尝试重现原始示例的节点之间的角度和关系。
然而,我的主要动机是OP的代码和目前接受的解决方案都会产生大量的海龟。这是一个问题,因为海龟被保存在全局列表中,而不是垃圾收集,因此不必要地创建它们会浪费空间。在深度4处,到目前为止显示的算法将创建30只在tree()
运行后不受欢迎且无法访问的海龟。我的解决方案允许您传入一只乌龟来绘制整个图表:
from math import acos
from turtle import Turtle, Screen
DOT_DIAMETER = 20
GENERATION_DISTANCE = 75
def tree(turtle, d, origin):
# d is the depth
turtle.penup()
turtle.setposition(origin)
turtle.dot(DOT_DIAMETER)
if d == 0: # base case
return
distance = (GENERATION_DISTANCE**2 + (2**d * DOT_DIAMETER / 2)**2)**0.5
angle = acos(GENERATION_DISTANCE / distance)
turtle.pendown()
turtle.left(angle)
turtle.forward(distance)
upper = turtle.position()
turtle.right(angle)
turtle.penup()
turtle.setposition(origin)
turtle.pendown()
turtle.right(angle)
turtle.forward(distance)
lower = turtle.position()
turtle.left(angle)
tree(turtle, d - 1, upper) # recurse upper branch
tree(turtle, d - 1, lower) # recurse lower branch
screen = Screen()
yertle = Turtle()
yertle.radians() # to accommodate acos()
tree(yertle, 3, (-150, 0))
screen.mainloop()
<强>输出:强>
您可以在screen.turtles()
之后致电tree()
查看已创建的海龟列表。
答案 2 :(得分:0)
解决方案的一种不错的方法是将高度限制作为参数传递给递归函数
过程:
示例(方括号内,每个节点–O-映射到实际的递归调用):
[ O ]
[ O ][ O ]
[ O ][ O ][ O ][ O ]
这是我的解决方案中的一小段代码(在GitHub存储库上找到整个程序:BinaryTreeVisualization)。
def draw_tree(bst, node_radius, root, bound_bottom, bound_top, x_pos, x_step):
if (root is not None):
# Drawing current subtree root
root_y = (bound_bottom + bound_top) // 2
draw_node(x_pos, root_y, node_radius)
# Drawing bottom subtree (bottom: same, top: root_y)
draw_tree(bst, node_radius, root.left, bound_bottom, root_y, x_pos + x_step, x_step)
# Drawing top subtree (bottom: root_y, top: same)
draw_tree(bst, node_radius, root.right, root_y, bound_top, x_pos + x_step, x_step)
pass
def draw_node(x, y, radius=5):
canvas.penup()
canvas.goto(x, y)
canvas.pendown()
canvas.dot(radius * 2)
pass
这是一棵树的example image(使用回购程序)