难以理解Python对河内塔的递归实现

时间:2016-12-21 12:47:45

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

我为河内塔问题找到了一个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,用 source = [2],helper = [],target = [1]。但是当我在程序上使用print时,我看到在我的难点之后和n = 2之前,函数确实将1移动到帮助器,情况是source = [2],helper = [1],target = []

即使n = 0,它是如何做到的?它的条件是只有n> 0才能执行?如何使用打印件来查看当时发生的情况?

1 个答案:

答案 0 :(得分: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]