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) 能用迭代的不用遞歸,遞歸調用函數,浪費空間,並且遞歸太深容易造成堆棧的溢出。