如果要理解什麼是遞迴,那麼漢諾塔是乙個非常經典的例子。幾乎所有的教科書都會提到漢諾塔。
漢諾塔有乙個非常有趣的傳說。
也就是說,當僧侶把64片金片從左邊按照規則移動到最右邊時,這個世界就會毀滅。
讀到這裡先不要緊張,讓我們來分析看看這位僧侶有沒有可能真的把64片金片都移到右邊去。
首先,我們可以給三個銀針進行分類:
首先,我們可以先將解開漢諾塔的步驟分解,分解步驟可以幫助我們簡化問題。這裡我們以5片漢諾塔為例:
我們都知道,如果要將金片全部移動到最右邊(目標銀針),我們首先得把第5片金片(最下面的)先移動到最右邊,因為其他可以移動的金片都比它小,所以不能放在它的上面。
第一步那麼,若要將第5片金片移到目標銀針,我們首先還得把第1,2,3,4片金片都挪到過渡銀針上,如下圖:
第二步接著,我們可以將第5片金片移動到目標銀針上面:
第三步然後我們再把過渡銀針上面的金片移動目標銀針上面就可以了。但注意,此時對於過渡銀針上的金片來說,起始銀針與過渡銀針的角色互換了。
每次我們要將第n個金片移動到目標銀針時,都需要
先將上方的n-1個金片移動到過渡銀針上
將第n個金片移動到目標銀針上
將過渡銀針上的n-1個金片移動到目標銀針上
以此類推,當我們準備將上方n-1個金片挪到過渡銀針上時,對於第n-1個金片來說,之前的過渡銀針就是它的目標銀針,而我們得先將上方的n-2個金片移動到另外乙個過渡銀針上面。在那之前,我們得把上方n-3個金片給…
由此可見,這是乙個遞迴過程,不停地將問題數量縮小,並且每乙個階段的邏輯都是一樣的。
因此,我們可以將**寫成遞迴的方式,只是在每一次遞迴呼叫的時候,起始銀針,過渡銀針以及目標銀針的角色總是會產生變化,因為對於不同階段的不同金片來說,他們的起始,過渡以及目標銀針是不一樣的。
注意每一次呼叫遞迴函式的時候,銀針每次都被作為不同角色的引數傳入,這表示對於每乙個金片來說,銀針的角色都在變化。
# numdisks: integer 當前起始銀針上需要考慮的金片
# source_rod: 起始銀針
# middle_rod: 過渡銀針
# target_rod: 目標銀針
defmove_hanoi_tower
(numdisks, source_rod, middle_rod, target_rod)
:# 如果當前起始銀針上需要考慮的金片只有1個的話,直接將其從起始銀針移動到目標銀針
if(numdisks ==1)
: target_rod.insert(
0, source_rod.pop(0)
)else
:# 否則,先將上方的金片都移動到過渡銀針。這裡過渡銀針被傳入當成目標銀針
move_hanoi_tower(numdisks-
1, source_rod, target_rod, middle_rod)
# 然後將當前的金片直接從起始銀針移動到目標銀針
target_rod.insert(
0, source_rod.pop(0)
)# 接著,再將過渡銀針上的金片移動到目標銀針。此時,過渡銀針作為這些金片的起始銀針
move_hanoi_tower(numdisks-
1, middle_rod, source_rod, target_rod)
通過將漢諾塔步驟分解為3步之後,我們便可以輕鬆計算出任意數量金片所需移動的最少步數了。
根據3步分解:
將n-1個金片移動到過渡銀針需要x步
將第n個金片移動到目標銀針需要1步
將n-1個金片從過渡銀針移動到目標銀針需要x步(同第一步需要一樣的步數)
我們可以得到移動n個金片最少需要步數:
x + 1 + x = 2x + 1
也就是說,每增加一塊金片所增加的步數,都是前一片金片步數的兩倍加上一步。
我們可以為此制定一張表來看看,我們知道只有一片金片的時候步數是1:
金片數量12
345…
64步數13
71531…
1.84 * 10^19
公式為:
2^n - 1(n為金片數量)
由此可見,若是要把64片金片移動到最右邊去,那需要的步數可是個天文數字啊!就是1秒鐘移動一片,到宇宙毀滅的那天也沒辦法完成。
所以,我們不必擔心當64片金片都移動到右邊的時候這個世界會毀滅,因為在那之前,宇宙已經先毀滅了。
Python(3)遞迴函式 漢諾塔
漢諾塔 有a,b,c三根柱子,在a柱子上從下往上按照大小順序摞著n圓盤。把圓盤從小到大重新擺放在柱子c上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動乙個圓盤。1.該問題可以分解成三個部分 把除最下面的圓盤,即 n 1 個圓盤,從a移到b 把最下面的圓盤從a移到c 把其餘 n 1 個...
python3 遞迴解漢諾塔問題
在經典漢諾塔問題中,有 3 根柱子及 n 個不同大小的穿孔圓盤,盤子可以滑入任意一根柱子。一開始,所有盤子自上而下按公升序依次套在第一根柱子上 即每乙個盤子只能放在更大的盤子上面 移動圓盤時受到以下限制 1 每次只能移動乙個盤子 2 盤子只能從柱子頂端滑出移到下一根柱子 3 盤子只能疊在比它大的盤子...
C 3個漢諾塔遞迴問題
移動次數2 n 1 hannoni int n,char a,char b,char c 把n個盤子借助b,從a移動到c move int n,char a,char c 把第n個盤子,從a移動到c include include using namespace std 漢諾塔問題a c 2 n 1...