我是Python新手,我目前正在阅读关于河内塔和递归的教程。我以为我理解了递归,直到他们给出了这个例子:
def moveTower(height,fromPole, toPole, withPole):
if height >= 1:
moveTower(height-1,fromPole,withPole,toPole)
moveDisk(fromPole,toPole)
moveTower(height-1,withPole,toPole,fromPole)
#print(withPole)
def moveDisk(fp,tp):
print("moving disk from",fp,"to",tp)
moveTower(3,"A","B","C")
打印3个光盘解决河内问题塔的正确动作: 将磁盘从A移动到B. 将磁盘从A移动到C. 将磁盘从B移动到C. 将磁盘从A移动到B. 将磁盘从C移动到A. 将磁盘从C移动到B. 将磁盘从A移动到B
我的问题是,它是如何做到的?!有人可以通过代码行,以便我了解它如何打印正确的动作?我主要对fp
和tp
的值如何从A
更改为B
到C
感到困惑。对不起,如果这是一个广泛的问题!任何帮助将不胜感激!
答案 0 :(得分:3)
在这个简单的例子中,您可以通过使用适当的print
来可视化所发生的事情,如下所示:
def moveTower(height,fromPole, toPole, withPole):
if height >= 1:
print( " "*(3-height), "moveTower:", height, fromPole, toPole )
moveTower(height-1,fromPole,withPole,toPole)
moveDisk(fromPole,toPole,height)
moveTower(height-1,withPole,toPole,fromPole)
#print(withPole)
def moveDisk(fp,tp,height):
print(" "*(4-height), "moving disk", "~"*(height), "from",fp,"to",tp)
moveTower(3,"A","B","C")
输出结果为:
moveTower: 3 A B
moveTower: 2 A C
moveTower: 1 A B
moving disk ~ from A to B
moving disk ~~ from A to C
moveTower: 1 B C
moving disk ~ from B to C
moving disk ~~~ from A to B
moveTower: 2 C B
moveTower: 1 C A
moving disk ~ from C to A
moving disk ~~ from C to B
moveTower: 1 A B
moving disk ~ from A to B
答案 1 :(得分:1)
这是它的作用。起始位置是:
A|321
B|
C|
然后使用moveTower(2,fromA,toC, withB)
,结果为:
A|3
B|
C|21
然后,moveDisk(fromA, toB)
做
A|
B|3
C|21
最后moveTower(2,fromC, toB)
结束游戏
A|
B|
C|321
这是河内的常用解决方案:将高度为h-1
的塔移至withPole
,将最大的光盘移至endPole
并移动高度为h-1
的塔到endPole
。
这是有效的,因为你可以移动最大光盘上h-1
高度塔的每张光盘。
要做moveTower(height-1,w,x)
,您可以将所有剩余的光盘放在所有3个塔中。
所以你会moveTower(height-2,y,z)
然后将第二大光盘移动到目的地,再次移动塔高-2。
编辑: this link中的图表最能说明我想说的话(“一张图片胜过千言万语”)。
如果您知道移动height-1
塔,那么只需执行算法中描述的3个步骤即可。 moveDisc
是“基本情况”(攀登第一步),moveTower是递归(如何从步骤n
转到n+1
)。
答案 2 :(得分:0)
主题涵盖here,但如果不熟悉概念,递归方法可能会令人困惑。该算法首先通过缓存挂钩递归地移动除最后一个盘(一个较小的问题实例)以外的所有盘,然后“实际”将最后一个盘移动到目标钉,然后将塔移动到初始挂钩。实际上,依靠递归,底部的磁盘被移动到目标挂钩,这是不可能直接做的,因为没有有效的移动。在递归调用中,三个pegs更改角色,以便始终将空挂钩变为缓存。如果您想象钉子不是排列在一条直线上而是一个圆圈中,这是最好的理解。与其他问题不同,这里首先进行递归调用,然后完成“实际”运动。
这个问题可以看作是this问题的副本。
答案 3 :(得分:0)
您应该打印每个moveTower的调用以查看其参数的更改。递归通常通过参数传播更改。序列号有助于显示顺序(当然,也可以订购打印到控制台)。
def seq_nummer():
num = 0
while True:
num += 1
yield num
seq_num = seq_nummer()
def moveTower(height, fromPole, toPole, withPole):
print("seq: %d" % seq_num.next())
print("height: %d, fromPole: %s, toPole: %s, withPole: %s" % (height, fromPole, toPole, withPole))
if height >= 1:
moveTower(height-1, fromPole, withPole, toPole)
moveDisk(fromPole, toPole)
moveTower(height-1, withPole, toPole, fromPole)
def moveDisk(fp,tp):
print("moving disk from",fp,"to",tp)
moveTower(3,"A","B","C")
答案 4 :(得分:0)
moveTower(height-1,fromPole,withPole,toPole)
使用第三根杆将所有光盘从初始极点移动到中间极点。
moveDisk(fromPole,toPole)
将最后一张光盘从初始极点移动到最终极点。现在最后一张光盘位于正确位置,无需移动。
moveTower(height-1,withPole,toPole,fromPole)
如果需要,使用第一根杆将所有光盘从中间极点移动到最终极点。