Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 河内巨蟒之塔-理解递归_Python_Algorithm_Recursion_Towers Of Hanoi - Fatal编程技术网

Python 河内巨蟒之塔-理解递归

Python 河内巨蟒之塔-理解递归,python,algorithm,recursion,towers-of-hanoi,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,toP

我是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
。对不起,如果这是一个有点广泛的问题!任何帮助都将不胜感激

本主题已涵盖,但是,如果不熟悉递归方法的概念,递归方法可能会令人困惑。该算法的工作原理是,首先通过缓存销钉递归移动除最后一个磁盘(一个较小的问题实例)以外的所有磁盘,然后“实际”将最后一个磁盘移动到目标销钉,然后将塔移动到初始销钉。实际上,依赖于递归,底部的磁盘被移动到目标peg,这是不可能直接执行的,因为没有有效的移动。在递归调用中,三个peg更改角色,使空peg始终成为缓存。如果你想象钉子不是排列成一条直线而是成一个圆圈,这一点最容易理解。与其他问题不同,这里递归调用首先出现,然后完成“实际”移动


这个问题可以看作是问题的复制品。

下面是它的作用。起始位置为:

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
移动到
带杆
,将最大的圆盘移动到
端杆
,并将高度塔
h-1
移动到
端杆

这是因为您可以在最大的圆盘上移动高度塔的每个圆盘
h-1

要执行
移动风塔(高度-1,w,x)
您可以将所有剩余的圆盘放置在所有3个风塔中

因此,您将
移动塔架(高度-2,y,z)
然后将第二大光盘移动到其目的地,然后再次移动塔架高度-2

编辑: 这张图表最好地描述了我想说的内容(“一幅画抵得上千言万语”)


如果您知道要移动高度为1的塔,只需执行算法中描述的3个步骤即可
moveDisc
是“基本情况”(爬上第一步),moveTower是递归(如何从步骤
n
n+1
)。

在这个简单的情况下,您可以通过使用适当的
打印来可视化发生的情况,如下所示:

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

您应该打印每个moveTower的调用,以查看其参数中的更改。递归通常通过参数传播更改。序列号有助于显示顺序(当然,控制台的打印也有顺序)

使用第三极将除一个外的所有圆盘从初始极移到中间极

moveDisk(fromPole,toPole)
将最后一个圆盘从初始极移到最终极。现在,最后一个光盘位于正确位置,无需移动

moveTower(height-1,withPole,toPole,fromPole)

如果需要,使用第一个磁极将所有光盘从磁极之间移动到最后一个磁极。

也许这个答案很有用:我建议将
打印(高度、fromPole、toPole、withPole)
粘贴在顶部,看看会发生什么!非常感谢所有回答问题的人!现在对我的理解更加自信:)非常感谢:)在您对输出的解释中,您省略了moveTower函数中的一个参数(例如moveTower:3ab,在我的示例中,moveTower(高度、fromPole、toPole、withPole))这仅仅是因为第三个参数没有真正使用吗?我可以去掉它吗?第三个参数是多余的,但是很方便,所以我建议把它留在代码中。输出应该是可视化各种递归操作的嵌套。另外,在输出中有移动磁盘,我假设这与我的移动磁盘有关?再次感谢!对不起,我知道这是很久以前的事了,我还是卡住了!今天我回到这里,我意识到我不明白在代码的这一部分:移动塔:3 A B移动塔:2 A C移动塔:1 A B(最上面的3行)为什么第3行是1 AB不是1 AC@十五边形
moveDisk(fromPole,toPole)
moveTower(height-1,withPole,toPole,fromPole)