1. 程式人生 > >漢諾塔 經典遞迴演算法 in python

漢諾塔 經典遞迴演算法 in python

   遞迴演算法,把大規模問題分解成容易解決而且求解方法相同的子問題,一般用遞迴函式實現,遞迴函式就是不斷呼叫自身的函式。

   舉個例子:

           

     俄羅斯套娃(應該都玩過,裡面最小的那個不能開啟,其他能開啟。從最小的娃娃開始,用稍大的那個娃娃套著,直至最大的一個套住所有的娃娃)。

     現在有如圖俄羅斯套娃,已經按正確的方法套好,裡面最小的那個娃娃背上寫了一個密碼。現在需要求解的問題是得到那個密碼,並且得到密碼後要把這套俄羅斯娃娃按正確的方法套好。

     那麼做法應該是,一層一層地開啟娃娃,直到看到最小的娃娃之後獲取密碼,然後一個一個的把娃娃合上。也就是,分別按順序對每一個娃娃進行開啟的操作,直至開啟到小娃娃,檢視密碼,然後再進行依次閉合娃娃的操作。

     這就是一個遞迴過程。而這個遞迴函式就是開啟閉合娃娃,判斷裡面的娃娃是否是最小的那個,如果是,獲取密碼,如果不是,開啟下一個娃娃,並且最後關閉當前娃娃。

虛擬碼如下:

# 娃娃編號從小到大依次遞增,為1~5
def getKey ( n ) :
	if n == 1 :   # 判斷當前娃娃是不是最小的那個娃娃
		讀取密碼   #進行操作
	else :
		getKey(n-1)   # 對當前娃娃套住的娃娃進行相同的操作 
		關閉娃娃      <span style="font-family: Arial, Helvetica, sans-serif;">#進行操作</span>

一個問題能否用遞迴求解,要看這個問題能不能逐層分解成一個個規模依次變小的小問題,同時有能夠進行判斷的下限(就是不能再小的子問題)。

而確定能夠用遞迴過程求解之後,關於求解步驟,可以直接分析最小的子問題跟比最小子問題“大1”的子問題。還需要知道的有:最小子問題的判斷依據以及處理步驟、如何遞迴呼叫自身。

       拿漢諾塔問題舉例:(藉助B柱,將A柱上的n塊盤子移動到C柱)

       最小的子問題就是:將一塊盤子從A移動到C柱

“大1”的子問題是:將兩塊盤子從A移動到C柱,不妨在草稿紙上畫個圖,顯然有三個步驟:

1.將最上面的盤子從A移動到B

2.將A下面的盤子從A移動到C

3.將B上的盤子移動到C

而程式呼叫自身則是逐次對(n-1)個盤子進行同樣的操作就可以解決n個盤子移動的問題。

只需以上三步分析就能得到這個遞迴程式的全部求解過程。

漢諾塔程式碼如下:

n = int(input("輸入初始化時A塔上盤子的個數n:\n"))
def move( n , A , B ,C ):   
	if n == 1 :       
		print( "%s is moved to %s" %(A ,C) )
	else :
		move( n-1 , A , C , B )   
		move( 1 , A , B , C )
		move( 1 , B , A , C )
move( n ,'A' , 'B' , 'C')	

如果還是不理解的話,自己動手寫一個遞迴程式最能加深理解。經典的遞迴問題有:Fibonacci數列、掃雷小遊戲。    

題外話:傳說古老印度在一個聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片聖廟,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片,一次只移動一片,不管在哪根針上,小片必在大片上面。當所有的金片都從梵天穿好的那根針上移到另外一概針上時,世界就將在一聲霹靂中消滅,梵塔、廟宇和眾生都將同歸於盡。

    n個盤子最少需要移動2^n-1,如果一秒鐘移動一次,計算出來需要5800多億年,那時候,地球還存在嗎?這樣看來,這個毀滅論倒是有一定道理的啊。