遞迴與棧
遞迴是一個重要的概念,同時也是一種重的程式設計方法。簡單地說,如果在一個函數、過程或資料結構的定義中又應用了它自身(作為定義項之一),那麼這個函數、過程或資料結構稱為是遞迴的定義的,簡稱遞迴。例如,階乘函數可遞迴定義如下:
必須注意,遞迴定義不能是"迴圈定義"。為此要求任可遞迴定義必須同時滿足如下兩個條件:
①被定義項在定義中的應用(即作為定義項的出現)具有更小的"尺度";
②被定義項在最小"尺度"上的定義不是遞迴的。
例如,在上述階乘函數的定義中,被定義項n!在定義中的應用(n-1)!具有比原來(即n)更小的"尺度"(即n-1)。同時,n!在最小"尺度"(即0)上的定義不是遞迴的(由自然數1直接定義)。這兩個條件實際上構成了遞迴程式設計的基本原則。此外,通常將反映條件②的部分寫在遞迴過程的開頭。
很多實際遞迴定義的。對於這些問題很容易寫出求解它們的遞迴演算法。計算階乘函數的遞迴演算法如下:
public static int nn(int i) {<br />if (i == 0) {<br />return 1;<br />} else<br />return i * nn(i - 1);<br />}
遞迴過程的運行引起遞迴調用。例如,f(3)的執行中出現的遞迴調用——返回過程3-5(a)所示。
f3 │ ↓ r└ |
①┌ ┌┈┘ ┈┘ |
f2 →┐ ↓ t└ |
②┌ ┌┈┘ ┈┘ |
f1 →┐ ↓ t└ |
③┌ ┌┈┘ ┈┘ |
f0 →┐ │ │ |
r1┌ │ ↓ |
←┐ └┈┐ 6 ⑥└ |
t1┌ ↓ ┈┘ |
←┐ └┈┐ 2 ⑤└ |
t1┌ ↓ ┈┘ |
←┐┈┈ └┈┐ 1 ④└ |
│ ↓ ┈┘1 |
圖3-5(a) f(3)執行遞迴調用─返回次序
|
|
top→ |
|
top→ |
|
top→ |
|
top→ |
|
top→ |
|
|
|
top→ |
調用f2前 |
|
調用f2後 |
|
調用f1後 |
|
調用f0後 |
|
返回f1後 |
|
返回f2後 |
top→ |
返回 f3後 |
圖3-5(b) 相應的工作棧狀態變化
遞迴調用——返回的控制與非遞迴過程的控制並無本質區別,同樣可由一個工作棧實現。對上述過程f,返回位置r應設在內、外層return語句這間。為了區別返回到哪一級遞迴,可在返回位置進棧的同時將該次調用的參數一起儲存。圖3-5(b)所示為與(a)相應的工作棧狀態變化過程。
原文地址:http://www.nhyz.org/nhxi/nhxi/jiegousuanfa/jiegou22.htm
歡迎: