遞歸是程式設計中極具威力的技巧,它允許方法直接或間接呼叫自身來解決問題。本文透過一個經典的 Java 範例——計算階乘,詳細示範如何實作簡單的遞歸演算法。
範例程式主要包含兩個類別:DiGui 作為主程式進入點,負責處理使用者輸入與輸出;Child 類別則封裝了遞歸邏輯。以下是完整的原始碼:
// CFAN 2002
// 遞歸演算法
// 求階乘
import java.io.*;
public class DiGui {
public static void main(String args[]) {
int i = 0;
char ch = ' ';
String s;
Child ren = new Child();
try {
System.out.println("Please input a Number, End with '#'");
do {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
s = br.readLine();
i = Integer.parseInt(s);
System.out.println(ren.Factorial(i));
} while (ch != '#');
} catch (IOException e) {}
}
}
class Child {
double Factorial(int n) {
if (n == 1)
return 1;
else
return n * Factorial(n - 1);
}
}
if (n == 1) return 1; 是遞歸的基準情況。當輸入值遞減至 1 時,停止遞歸呼叫並返回 1,防止無限遞歸導致堆疊溢位。
return n * Factorial(n - 1); 將問題分解為「當前數值 × (n-1) 的階乘」。每次呼叫都會在堆疊中保留當前狀態,直到觸發終止條件,隨後層層回溯計算最終結果。
Child 物件並進入迴圈等待使用者輸入Factorial() 方法if (n <= 1) return 1;ch 永遠為空格,無法透過 '#' 結束迴圈。應改為檢查輸入字串 sdouble 回傳型別雖能處理較大數值,但會失去精度。大數運算建議使用 BigIntegerBufferedReader 應在 finally 區塊或 try-with-resources 中關閉import java.io.*;
import java.math.BigInteger;
public class FactorialCalculator {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("請輸入非負整數 (輸入 'q' 結束):");
String input;
while ((input = br.readLine()) != null) {
if ("q".equalsIgnoreCase(input)) break;
try {
int n = Integer.parseInt(input.trim());
if (n < 0) {
System.out.println("請輸入非負整數!");
continue;
}
System.out.println(n + "! = " + factorial(BigInteger.valueOf(n)));
} catch (NumberFormatException e) {
System.out.println("輸入格式錯誤,請重新輸入!");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
static BigInteger factorial(BigInteger n) {
return n.equals(BigInteger.ZERO) || n.equals(BigInteger.ONE)
? BigInteger.ONE
: n.multiply(factorial(n.subtract(BigInteger.ONE)));
}
}
雖然遞歸程式碼優雅簡潔,但每次呼叫都消耗堆疊空間。對於階乘這類線性遞歸,迭代寫法效能更佳且無堆疊溢位風險:
static BigInteger factorialIterative(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
遞歸是解決分治型問題的利器,階乘計算雖為入門範例,卻完整展示了「終止條件」、「遞歸呼叫」與「回溯計算」三大核心要素。實務開發中需權衡可讀性與效能,並妥善處理邊界條件與資源管理。