【问题标题】:Difficulty understanding Python's recursive implementation of Hanoi Towers难以理解 Python 递归实现 Hanoi Towers
【发布时间】:2016-12-22 02:05:11
【问题描述】:

我为 Hanoi Towers 问题找到了 Python 代码 online。该代码有效,但我很难理解它。这里是:

def hanoi(n, source, helper, target):
    if n > 0:
        # move tower of size n - 1 to helper:
        hanoi(n - 1, source, target, helper)
        # move disk from source peg to target peg
        if source:
            target.append(source.pop())
        # move tower of size n-1 from helper to target
        hanoi(n - 1, helper, source, target)


source = [2, 1]
target = []
helper = []
hanoi(len(source), source, helper, target)

print (source, helper, target)

我对最后一部分有困难:

hanoi(n - 1, helper, source, target)

据我所知,发生的唯一移动是通过 target.append(source.pop()) 行。当我们使用 [2,1] 的简单列表时,在我们将 1 移动到目标列表后,它会以某种方式将 1 移动到辅助列表,但是如何???

我的看法,下面是程序运行的方法:它到达n = 0,什么都不做,返回n = 1,将1移动到目标,然后它到达我的难点,并执行

hanoi(n - 1, helper, source, target)

但由于 n-1 = 0,它什么也不做,然后它应该继续移动到 n = 2,与 源 = [2],助手 = [],目标 = [1]。但是当我在程序上使用打印时,我看到在我的困难点之后和 n = 2 之前,该函数确实将 1 移动到了助手,情况是 source = [2], helper = [1], target = []

即使 n = 0,它是如何做到的?它有一个条件,只有当 n>0 时它才会执行?我如何使用打印来查看那一刻发生了什么?

【问题讨论】:

  • 诀窍在于参数的顺序:您可以看到助手和目标交换。
  • 您是否尝试过添加一些prints,或者使用例如pythontutor.com 可视化发生了什么?
  • @DanielRoseman 仍然,n = 0,这意味着条件 n > 0 不满足!当 n = 0 时,该函数不应该什么都不做!
  • @blz 如果n <= 0,函数只返回None,是的。
  • @jonrsharpe 然而,当我们在 n = 1 的情况下执行 hanoi(n - 1, helper, source, target) 行时,它会以某种方式将 1 从目标移动到助手

标签: python python-3.x recursion towers-of-hanoi


【解决方案1】:

我已插入标准跟踪打印语句:每次我们进入或退出例程时,以及在关键处理连接处。我还添加了缩进以帮助显示调用级别。

还有一个技巧可以为您说明问题:我为每个堆栈添加了一个字符标签,然后将 n 减一,这样我们就不会移动这些标签。这使您可以在每次调用时准确查看每个角色中的堆栈。

输出应该向您显示每次调用中移动的内容,以及在所有磁盘洗牌中递归发生的位置。当你有了 2 个磁盘的想法时,尝试用 3 个。当你开始理解时,将其扩展到 4 个并注释掉一两个跟踪语句——也许只是观察动作。

indent = ""

def hanoi(n, source, helper, target):
    global indent
    indent += "  "
    print (indent, "ENTER", n, source, helper, target)
    if n > 0:
        # move tower of size n - 1 to helper:
        hanoi(n - 1, source, target, helper)
        # move disk from source peg to target peg
        if source:
            print (indent, "MOVE disk", source[-1], "from", source[0], "to", target[0])
            target.append(source.pop())
        # move tower of size n-1 from helper to target
        hanoi(n - 1, helper, source, target)

    print (indent, "LEAVE", n, source, helper, target)
    indent = indent[:-2]


source = ['A', 2, 1]
helper = ['B', ]
target = ['C', ]

print (source, helper, target)
hanoi(len(source)-1, source, helper, target)
print (source, helper, target)

输出:

['A', 2, 1] ['B'] ['C']
   ENTER 2 ['A', 2, 1] ['B'] ['C']
     ENTER 1 ['A', 2, 1] ['C'] ['B']
       ENTER 0 ['A', 2, 1] ['B'] ['C']
       LEAVE 0 ['A', 2, 1] ['B'] ['C']
     MOVE disk 1 from A to B
       ENTER 0 ['C'] ['A', 2] ['B', 1]
       LEAVE 0 ['C'] ['A', 2] ['B', 1]
     LEAVE 1 ['A', 2] ['C'] ['B', 1]
   MOVE disk 2 from A to C
     ENTER 1 ['B', 1] ['A'] ['C', 2]
       ENTER 0 ['B', 1] ['C', 2] ['A']
       LEAVE 0 ['B', 1] ['C', 2] ['A']
     MOVE disk 1 from B to C
       ENTER 0 ['A'] ['B'] ['C', 2, 1]
       LEAVE 0 ['A'] ['B'] ['C', 2, 1]
     LEAVE 1 ['B'] ['A'] ['C', 2, 1]
   LEAVE 2 ['A'] ['B'] ['C', 2, 1]
['A'] ['B'] ['C', 2, 1]

【讨论】:

    猜你喜欢
    • 2018-03-26
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 2016-02-22
    • 1970-01-01
    相关资源
    最近更新 更多