引子
從前有座山,山上有座廟,廟裏有個老和尚,老和尚在給小和尚講故事,故事講的是從前有座山,山上有座廟,廟裏有個老和尚,老和尚在給小和尚講故事,故事講的是從前有座山,山上有座廟,廟裏有個老和尚,老和尚在給小和尚講故事,故事講的是從前有座山,山上有座廟,廟裏有個老和尚,老和尚在給小和尚講故事,故事講的是從前有座山,山上有座廟,廟裏有個老和尚,老和尚在給小和尚講故事,故事講的是......
這個例子,如果用java程序來演示,會是這個樣子:
public class Hello {
public static void main(String[] args) {
sayStory();
}
static void sayStory(){
System.out.println("從前有座山,山上有座廟,廟裏有個老和尚,老和尚在給小和尚講故事,故事講的是");
sayStory();
}
}
程序運行結果:
故事在一直講下去。
看一下java代碼中,在方法sayStory()中又調用了sayStory()。
遞歸概述
什麼是遞歸
遞歸,英文爲Recursion, 在計算機科學中,遞歸指得是在函數的定義中使用函數自身。
遞歸,包含了兩個意思:遞 和 歸。遞是隻傳遞下去,歸是指歸來,也就是說,遞歸有去也有回。
那麼,上面的講故事的程序,算遞歸程序嗎?
在方法sayStory()中又調用了sayStory(),符合遞歸的一個條件,即傳遞,但是,這個程序,沒有歸來,所以,程序會一直運行下去,直到資源耗盡,程序出錯:
因此,這不是個完整的遞歸程序。
遞歸要素
首先,遞歸必須要申明一個函數,且在函數中調用自身。
另外,遞歸要有明確的終止條件,遞歸就是有去有回,必然有一個明確的重點,到達這個終點後,就不再往下遞,而是開始往回歸來。
遞歸的內涵
遞歸的核心思想,就是把規模大的問題轉化爲規模小的相似的子問題來解決。在函數實現時,因爲解決大問題的方法和解決小問題的方法往往是同一個方法,所以就產生了函數調用它自身的情況,這也正是遞歸的定義所在。
考慮一下,遞歸的數學模型,很像數學歸納法。數學歸納法適用於將解決的原問題轉化爲解決它的子問題,而它的子問題又變成子問題的子問題。歸納法解決數學問題一般分爲下面3個步驟:
1:步進表達式:問題演算成子問題的表達式
2:結束條件:什麼時候可以不再使用步進表達式
3:求解表達式:在結束條件下能夠直接計算返回值的表達式
比如,斐波那契數列,使用數學歸納法,3個步驟爲:
1: 推導出計算表達式: F(n)=F(n-1)+F(n-2) (n≥3)
2:結束條件:n=1,n=2時
3:求解表達式: F(1)=F(2)=1
遞歸的編程模型
明確了遞歸的數學模型後,我們就要看,如果通過編程來實現遞歸。一般的,有兩種編程模型:
模型一: 先處理問題,然後再往下傳遞
遞歸函數(大規模){
if (end_condition){ // 遞歸終止條件
end;
}else{
solve; // 處理問題
遞歸函數(小規模); // 分解問題規模,傳遞下去
}
}
模型二: 在歸來的過程中處理問題
遞歸函數(大規模){
if (end_condition){ // 遞歸終止條件
end;
}else{
遞歸函數(小規模); //分解問題規模,傳遞下去
solve; // 歸來,處理問題
}
}
下面,演示一下,使用遞歸的編程模型,解決斐波那契數列問題。
首先,需要什麼一個函數,問題規模爲n,問題的結果爲一個整數。
則函數可以聲明爲:int fib(int n)
然後,確定終止條件: n=1,n=2時
3:求解表達式:
F(n)=F(n-1)+F(n-2) (n≥3)
F(1)=1,F(2)=1
則代碼如下:
案例演示
階乘
階乘n!的數學定義: n!=1234…..(n-1)n,並規定 1!=1。
因此,2!=21=2(1!),3!=3(21)=3(2!),
4!=4(321)=4(3!)
5!=5(4321)=54!
根據規律,可以推斷出: n!=n*(n-1)!,這就是階乘的遞歸公式。
並且可以明確遞歸的終止條件n=1,終止時的值爲1。
下面,想一下,如何用java程序來實現呢?
遞歸函數原型,可以什麼爲:int factorial(int n);
則函數的遞歸調用表達式爲: factorial(n)=n* factorial(n-1)
具體代碼如下:
public class Hello {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入n:");
int n = sc.nextInt();
int f = factorial(n);
System.out.println("結果是:" + f);
}
static int factorial(int n) {
if (n == 1)
return 1;
else
return n * factorial(n - 1);
}
}
更多案例,請看下一章節。