我为河内塔问题找到了一个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才能执行?如何使用打印件来查看当时发生的情况?
答案 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]