1. 程式人生 > 實用技巧 >漢諾塔-遞迴演算法

漢諾塔-遞迴演算法

遞迴是一種強大的程式設計技術,他把一個問題分解為一組相似的子問題,每一問題都用一個尋常解去解決。遞迴函式就是會直接或者間接呼叫自身的一種函式,一般來說,一個遞迴函式呼叫自身去解決它的子問題。

"漢諾塔"經典遞迴問題

"漢諾塔"是印度的一個古老傳說,也是程式設計中的經典的遞迴問題,是一個著名的益智遊戲:

  題目如下:

    塔上有三根柱子和一套直徑各不相同的空心圓盤,開始時源柱子上的所有圓盤都按從大到小的順序排列。目標是通過每一次移動一個圓盤到另一根柱子上,最終把一堆圓盤移動到目標柱子上,過程中不允許把較大的圓盤放置在較小的圓盤上;

    

尋找規律(把所有的圓盤移動到C):

  1)n(圓盤個數) == 1

    第一次:1號盤 A -> C sum(移動次數) = 1

  2)n == 2

    第一次:1號盤 A -> B

    第二次:2號盤 A -> C

    第三次:1號盤 B -> C  sum = 3

  3)n == 3

    第一次:1號盤 A -> C

    第二次:2號盤 A -> B

    第三次:1號盤 C -> B

    第四次:3號盤 A -> C

    第五次:1號盤 B -> A

    第六次:2號盤 B -> C

    第七次:1號盤 A -> C  sum = 7

  以此類推...

  故不難發現規律,移動次數為:sum = 2^n - 1 

演算法分析(遞迴):

  把一堆圓盤從一個柱子移動另一根柱子,必要時使用輔助的柱子。可以把它分為三個子問題:

    首先,移動一對圓盤中較小的圓盤到輔助柱子上,從而露出下面較大的圓盤,

    其次,移動下面的圓盤到目標柱子上

    最後,將剛才較小的圓盤從輔助柱子上在移動到目標柱子上

   把三個步驟轉化為簡單數學問題:

    (1) 把 n-1個盤子由A 移到 B;

    (2) 把第n個盤子由 A移到 C;

    (3) 把n-1個盤子由B 移到 C;

  我們建立一個JS函式,當它呼叫自身的時候,它去處理當前正在處理圓盤之上的圓盤。最後它回一個不存在圓盤去呼叫,在這種情況下,它不在執行任何操作。

JavaScript原始碼實現

var hanoi = function(disc,src,aux,dst){
    
    if(disc>0){

        hanoi(disc-1,src,dst,aux);

        console.log(' 移動 '+ disc +  ' 號圓盤 ' + ' 從 ' + src +  ' 移動到 ' +  dst);

        hanoi(disc-1,aux,src,dst)

    }

}

hanoi(3,'A','B','C')

整個演算法的思路是:

  1. 將A柱子上的n-1個盤子暫時移到B柱子上
  2. A柱子只剩下最大的盤子,把它移到目標柱子C上
  3. 最後再將B柱子上的n-1個盤子移到目標柱子C上