河内蟒蛇塔 - 理解递归

时间:2014-04-16 11:05:01

标签: python algorithm recursion towers-of-hanoi

我是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

我的问题是,它是如何做到的?!有人可以通过代码行,以便我了解它如何打印正确的动作?我主要对fptp的值如何从A更改为BC感到困惑。对不起,如果这是一个广泛的问题!任何帮助将不胜感激!

5 个答案:

答案 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)

如果需要,使用第一根杆将所有光盘从中间极点移动到最终极点。