[英]Difficulty understanding Python's recursive implementation of Hanoi Towers
我在網上找到了有關河內塔樓問題的Python代碼。 該代碼有效,但是我很難理解它。 這里是:
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才執行? 我該如何使用照片來查看當時的情況?
我插入了標准的跟蹤打印語句:每次我們進入或退出例程時,以及在關鍵處理結點處。 我還縮進以幫助顯示通話水平。
還有一些騙子可以為您說明問題:我向每個堆棧中添加了一個字符標簽,然后將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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.