1.遞迴的定義:
程式直接或間接的呼叫自身的方法。
遞迴演算法的特點:
(1) 遞迴就是在過程或函式裡呼叫自身。
(2) 在使用遞迴策略時,必須有一個明確的遞迴結束條件,稱為遞迴出口。
(3) 遞迴演算法解題通常顯得很簡潔,但遞迴演算法解題的執行效率較低。所以一般不提倡用遞迴演算法設計程式。
(4) 在遞迴呼叫的過程當中系統為每一層的返回點、區域性量等開闢了棧來儲存。遞迴次數過多容易造成棧溢位等。所以一般不提倡用遞迴演算法設計程式。
遞迴演算法的程式碼,可以分成兩個部分:遞迴部分包括遞迴程式碼的主體和遞迴出口(需要滿足的輸出條件)。把整體運算轉換為分步運算。
案例:漢諾塔
這個例子可以用遞迴演算法實現。
ABC分別是123柱子,程式碼思路大概是這樣的
把N-1層的環子先通過C移到B,最後再把第N層的最大的環子移到C,這個時候就剩下一個N-1層的新“塔”,那麼我們把他看成一個新的“塔”把B柱看成之前的A柱,通過C柱把(N-1)-1層移到A柱,再把第N-1層的最大(原本第二大)的環子放到C,如此迴圈到最後的N=1 。
實現方法:
1 #include<iostream> 2 using namespace std; 3 void hanoi(int n,char a,char b,char c) 4 { 5 if(n==1) 6 cout<<n<<" "<<a<<" "<<c<<endl; 7 else 8 { 9 hanoi(n-1,a,c,b); 10 cout<<n<<" "<<a<<" "<<c<<endl; 11 hanoi(n-1,b,a,c); 12 } 13 } 14 int main() 15 { 16 int n; 17 cout<<"輸入正整數:"<<endl; 18 cin>>n; 19 cout<<"結果為"<<endl; 20 hanoi(n,'A','B','C'); 21 22 23 return 0; 24 }
2.分析:
從演算法結構來說,遞迴宣告的結構並不總能夠轉換為迭代結構,原因在於結構的引申本身屬於遞迴的概念,用迭代的方法在設計初期根本無法實現,這就像動多型的東西並不總是可以用靜多型的方法實現一樣。這也是為什麼在結構設計時,通常採用遞迴的方式而不是採用迭代的方式的原因,一個極典型的例子類似於連結串列,使用遞迴定義及其簡單,但對於記憶體定義(陣列方式)其定義及呼叫處理說明就變得很晦澀,尤其是在遇到環鏈、圖、網格等問題時,使用迭代方式從描述到實現上都變得不現實。因而可以從實際上說,所有的迭代可以轉換為遞迴,但遞迴不一定可以轉換為迭代。採用遞迴演算法需要的前提條件是,當且僅當一個存在預期的收斂時,才可採用遞迴演算法,否則,就不能使用遞迴演算法。
遞迴的優點:
1)大問題化為小問題,可以極大的減少程式碼量;
2)用有限的語句來定義物件的無限集合.;
3)程式碼更簡潔清晰,可讀性更好
遞迴的缺點
1)遞迴呼叫函式,浪費空間;
2)遞迴太深容易造成堆疊的溢位;
迭代的優點:
1)迭代效率高,執行時間只因迴圈次數增加而增加;
2)沒什麼額外開銷,空間上也沒有什麼增加,
迭代的缺點:
1) 不容易理解;
2) 程式碼不如遞迴簡潔;
3) 編寫複雜問題時困難。
3.兩者之間的關係
1) 遞迴中一定有迭代,但是迭代中不一定有遞迴,大部分可以相互轉換。
2) 能用迭代的不用遞迴,遞迴呼叫函式,浪費空間,並且遞迴太深容易造成堆疊的溢位。