一、執行個體說明
漢諾塔問題:傳說在古代印度的貝拿勒斯聖廟裡,安放了一塊黃銅板,板上插了三根寶石砫,在其中一根寶石砫上,自上而下按由小到大的順序串有64個金盤。這就是漢諾塔遊戲。要求將左邊柱子上的64個金盤按照下面的規則移到右邊的柱子上。2-1所示:
規則:
a) 一次只能移一個盤子。
b) 盤子只能在三個柱子上存放。
c) 任何時候大盤不能放在小盤上面。
圖2-1 漢諾塔
二、基礎知識點
漢諾塔是非常經典的關於遞迴程式的例子,讀者如果將來要從事程式開發工作,則務必要掌握遞迴程式的設計方法。遞迴是程式設計中一個強有力的工具,有很多數學函數是遞迴定義的,比如大家熟悉的階乘函數。
下面來簡要分析一下漢諾塔問題是如何通過遞迴來解決的。
簡化問題:
設盤子只有一個,則本問題可簡化為a→b。
對於大於一個盤子的情況,邏輯上可分為兩部分:第n個盤子和除n個以外的n-1個盤子。如果將除n以外的n-1個盤子看成一個整體,則要解決本問題,可按以下步驟:
a、將a杆上n-1個盤子藉助於b先移到c杆; a→c (n-1,a,c,b)
b、將a杆上第n個盤子從a移到b杆; a→b
c、將c杆上n-1個盤子藉助a移到b杆。 c→b (n-1,c,b,a)
三、技術要點
本例主要應用了if條件陳述式,主要把問題分為一個盤子的情況和大於一個盤子的情況。
文法:(兩程式語句擇一執行)
if(條件式)
{
程式語句1
}
else
{
程式語句2
}
遞迴程式的調用主要是通過在某函數內部再次調用本函數來實現。
四、實現步驟
首先建立一個類,命名為Hanio.java,在Hanio.java檔案中鍵入下列代碼:
public class Hanio {
public static void main(String args[]) {
//一共有兩個盤子
byte n = 2;
// 定義三個杆子的名稱
char a = 'A', b = 'B', c = 'C';
// 調用漢諾塔執行函數
hanio(n, a, b, c);
}
public static void hanio(byte n, char a, char b, char c) {
if (n == 1) { //如果只有一個盤子則直接把盤子從a 移到b
System.out.println("move " + a + " to " + b);
}
else { //超過一個盤子的情況
hanio( (byte) (n - 1), a, c, b); //將a杆上n-1個盤子藉助於b先移到c杆
System.out.println("move " + a + " to " + b); //將a杆上第n個盤子從a移到b杆
hanio( (byte) (n - 1), c, b, a); //將c杆上n-1個盤子藉助a移到b杆
}
}
}
五、歸納總結
如果一個問題能夠簡化成類似階乘函數的形式,就可以用遞迴來實現,即在程式設計中,函數可以遞迴調用,主要利用了電腦的堆棧機制。遞迴函式結構清晰,程式易讀,而且它的正確性容易得到證明。