Python學習 - 漢諾塔的實現思想 (遞歸函數)

這兩天在學習Python的基本知識,學到函數的遞歸調用時,用漢諾塔來舉例子是一個很好的方式,這裏把實現思想和代碼簡單說明一下。

漢諾塔 (hanoi)的由來

法國數學家愛德華·盧卡斯曾編寫過一個印度的古老傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裏,一塊黃銅板上插着三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消滅,而梵塔、廟宇和衆生也都將同歸於盡。

漢諾塔的原理展示

  • A,B,C三個柱子,盤子在A柱子上按金字塔形狀從小到大排列
  • 每次只能移動一個盤子
  • 任何一次移動,必須大盤子在下面,小盤子在上面
  • 最後盤子按順序從放到C上
    漢諾塔移動示意圖

###漢諾塔的移動步驟
####前提條件: 有ABC三個柱子,起初所有的盤子在A柱上(最左邊),通過不斷的移動,把盤子移到最右邊的C柱子上。

實現步驟:

1. 只有一個盤子1
    - 把1從A直接挪到C  (A --> C)
2. 倆個盤子1,2
    - 把1從A挪到B    (A --> B)
    - 把2挪到C       (A --> C)
    - 把1從B挪到C    (B --> C)
3. 三個盤子1,2,3
    - 把上面兩個藉助C先移到B   (2, A-->C-->B):  這裏可以不看最底下個盤子,先看上面的兩個盤子,藉助C先移到B,這裏跟兩個盤子的移動是一樣的。
	- 把1 移到C  (A --> C)
        - 把2 移到B (A --> B)
	- 把1 移到B (C --> B)
    - 把最底下的盤子3移到C               
	- A --> C 
    - 把 1,2 從B藉助A移到C  (1,2 在B柱)(2, B-->A-->C)
        - 把 1 移到A
        - 把 2 移到C
        - 把 1 移到C
4. N個盤子 
     - 把上面N-1個先移到B柱 (N-1,A-->C-->B)
     - 把底下第N個移到C柱    (1,A-->C)
     - 把N-1個盤藉助A移到C   (N-1, B-->A-->C)

Python代碼的漢諾塔實現方式

# 漢諾塔的實現方式
# n: 代表多少個盤子
# A, B, C 代表 起始盤子A,輔助盤子B,目的盤子C

#表示移動位置,從a到b
def move(a,b):
    print(a,"-->",b)
    
# 漢諾塔實現
def hanoi(n, A, B, C):
    if n == 1:
        move(A,C)
        return None
    if n == 2:
        move(A,B)
        move(A,C)
        move(B,C)
        return None
    if n >= 3:
        hanoi(n-1,A, C, B)    #上面的N-1個盤子從A上,藉助C,移到B
        move(A,C)             # 把左邊最底下的盤子從A移到C
        hanoi(n-1, B, A, C)   # 在B上個N-1個盤子,藉助B移到C
        
# 測試
print("1個盤子")
hanoi(1,"A", "B", "C")
print("2個盤子")
hanoi(2,"A", "B", "C")
print("3個盤子")
hanoi(3,"A", "B", "C")        
print("5個盤子 ")
hanoi(5,"A", "B", "C")

思考:其實這裏去掉N=2的實現,結果也是一樣的,在這裏多寫一步N=2, 是爲了代碼的方便閱讀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章