遞歸與分治策略
直接或間接地調用自身的算法稱為遞歸算法。用函數自身給出定義的函數稱為遞歸函數。
在計算機算法設計與分析中,使用遞歸技術往往使函數的定義和算法的描述簡潔且易於理解。
例1 階乘函數

可遞歸地定義為:
其中:
n=0 時,n!=1為邊界條件
n>0 時,n!=n(n-1)!為遞歸方程
邊界條件與遞歸方程是遞歸函數的二個要素,遞歸函數只有具備了這兩個要素,才能在有限次計算后得出結果。
例2 Fibonacci數列
無窮數列1,1,2,3,5,8,13,21,34,55,…,被稱為Fibonacci數列。它可以遞歸地定義為:
第n個Fibonacci數可遞歸地計算如下:
其中:
n=0 時,n!=1為邊界條件
n>0 時,n!=n(n-1)!為遞歸方程
邊界條件與遞歸方程是遞歸函數的二個要素,遞歸函數只有具備了這兩個要素,才能在有限次計算后得出結果。
例2 Fibonacci數列
無窮數列1,1,2,3,5,8,13,21,34,55,…,被稱為Fibonacci數列。它可以遞歸地定義為:
第n個Fibonacci數可遞歸地計算如下:
int fibonacci(int n){ if (n <= 1) return 1; return fibonacci(n-1)+fibonacci(n-2); }
遞歸需要有邊界條件、遞歸前進段和遞歸返回段。
當邊界條件不滿足時,遞歸前進;
當邊界條件滿足時,遞歸返回。
注意:在使用遞增歸策略時,必須有一個明確的遞歸結束條件,稱為遞歸出口,否則將無限進行下去(死鎖)。
遞歸的缺點:
遞歸算法解題的運行效率較低。
在遞歸調用過程中,系統為每一層的返回點、局部變量等開辟了堆棧來存儲。遞歸次數過多容易造成堆棧溢出等。
例3逆序輸出一個正數中的每一位數
例如,對於數12345,依次輸出5 4 3 2 1
分析: 如果n/10==0,則 輸出n; 否則 輸出n%10, 然后,對n/10進行相同處理
當邊界條件不滿足時,遞歸前進;
當邊界條件滿足時,遞歸返回。
注意:在使用遞增歸策略時,必須有一個明確的遞歸結束條件,稱為遞歸出口,否則將無限進行下去(死鎖)。
遞歸的缺點:
遞歸算法解題的運行效率較低。
在遞歸調用過程中,系統為每一層的返回點、局部變量等開辟了堆棧來存儲。遞歸次數過多容易造成堆棧溢出等。
例3逆序輸出一個正數中的每一位數
例如,對於數12345,依次輸出5 4 3 2 1
分析: 如果n/10==0,則 輸出n; 否則 輸出n%10, 然后,對n/10進行相同處理
void Reverse( int n){ if(n/10==0) cout<<n; else{ cout<<n%10; Reverse(n/10); } } main(){ Reverse(12345); }
順序輸出一個正數中的每一位數
例如,對於數12345,依次輸出1 2 3 4 5
分析: 如果n/10==0,則 輸出n; 否則 先對n/10進行相同處理之后,cout<<n%10;
void Reverse( int n){ if(n/10==0) cout<<n; else{ Reverse(n/10); cout<<n%10; } } main(){ Reverse(12345); }