深究遞歸和迭代的區別、聯繫、優缺點及實例對比

http://blog.csdn.net/laoyang360/article/details/7855860ios

http://www.zhihu.com/question/20278387程序員

深究遞歸和迭代的區別、聯繫、優缺點及實例對比

1.概念區分算法

遞歸的基本概念:程序調用自身的編程技巧稱爲遞歸,是函數本身調用本身.編程

一個函數在其定義中直接或間接調用自身的一種方法,它一般把一個大型的複雜的問題轉化爲一個與原問題類似的規模較小的問題來解決,能夠極大的減小代碼量.遞歸的能力在於用有限的語句來定義對象的無限集合.數組

使用遞歸要注意的有兩點:網絡

1)遞歸就是在過程或函數裏面調用自身;數據結構

2)在使用遞歸時,必須有一個明確的遞歸結束條件,稱爲遞歸出口.函數

遞歸分爲兩個階段:spa

1)遞推:把複雜的問題的求解推到比原問題簡單一些的問題的求解;.net

2)迴歸:當得到最簡單的狀況後,逐步返回,依次獲得複雜的解.

利用遞歸能夠解決不少問題:如揹包問題,漢諾塔問題,...等.

斐波那契數列爲:0,1,1,2,3,5...

因爲遞歸引發一系列的函數調用,而且有可能會有一系列的重複計算,遞歸算法的執行效率相對較低.

迭代:利用變量的原值推算出變量的一個新值.若是遞歸是本身調用本身的話,迭代就是A不停的調用B.

2.辯證看遞歸和迭代

所謂遞歸,簡而言之就是應用程序自身調用自身,以實現層次數據結構的查詢和訪問。遞歸的使用可使代碼更簡潔清晰,可讀性更好(對於初學者到不見得),但因爲遞歸須要系統堆棧,因此空間消耗要比非遞歸代碼要大不少,並且,若是遞歸深度太大,可能系統資源會不夠用。

每每有這樣的觀點:能不用遞歸就不用遞歸,遞歸均可以用迭代來代替。

誠然,在理論上,遞歸和迭代在時間複雜度方面是等價的(在不考慮函數調用開銷和函數調用產生的堆棧開銷),但實際上遞歸確實效率比迭代低,既然這樣,遞歸沒有任何優點,那麼是否是就,沒有使用遞歸的必要了,那遞歸的存在有何意義呢?

萬物的存在是須要時間的檢驗的,遞歸沒有被歷史所埋沒,即有存在的理由。從理論上說,全部的遞歸函數均可以轉換爲迭代函數,反之亦然,然而代價一般都是比較高的。但從算法結構來講,遞歸聲明的結構並不總可以轉換爲迭代結構,緣由在於結構的引伸自己屬於遞歸的概念,用迭代的方法在設計初期根本沒法實現,這就像動多態的東西並不老是能夠用靜多態的方法實現同樣。這也是爲何在結構設計時,一般採用遞歸的方式而不是採用迭代的方式的緣由,一個極典型的例子相似於鏈表,使用遞歸定義及其簡單,但對於內存定義(數組方式)其定義及調用處理說明就變得很晦澀,尤爲是在遇到環鏈、圖、網格等問題時,使用迭代方式從描述到實現上都變得不現實。於是能夠從實際上說,全部的迭代能夠轉換爲遞歸,但遞歸不必定能夠轉換爲迭代。

採用遞歸算法須要的前提條件是,當且僅當一個存在預期的收斂時,纔可採用遞歸算法,不然,就不能使用遞歸算法。

遞歸實際上是方便了程序員難爲了機器,遞歸能夠經過數學公式很方便的轉換爲程序。其優勢就是易理解,容易編程。但遞歸是用機制實現的,每深刻一層,都要佔去一塊棧數據區域,對嵌套層數深的一些算法,遞歸會力不從心,空間上會之內存崩潰而了結,並且遞歸也帶來了大量的函數調用,這也有許多額外的時間開銷。因此在深度大時,它的時空性就很差了。

而迭代雖然效率高,運行時間只因循環次數增長而增長,沒什麼額外開銷,空間上也沒有什麼增長,但缺點就是不容易理解,編寫複雜問題時困難。

於是,「能不用遞歸就不用遞歸,遞歸均可以用迭代來代替」這樣的理解,仍是辯證的來看待,不可一棍子打死。*/

1,2部分摘自網絡,略有改動,向原做者致敬!

3.我的總結

 

定義

優勢

缺點

遞歸

程序調用自身的編程技巧稱爲遞歸

1)大問題化爲小問題,能夠極大的減小代碼量;

2)用有限的語句來定義對象的無限集合.;

3)代碼更簡潔清晰,可讀性更好

1)遞歸調用函數,浪費空間;

2)遞歸太深容易形成堆棧的溢出;

 

迭代

利用變量的原值推算出變量的一個新值,迭代就是A不停的調用B.

1)迭代效率高,運行時間只因循環次數增長而增長;

2)沒什麼額外開銷,空間上也沒有什麼增長,

1) 不容易理解;

2) 代碼不如遞歸簡潔;

3) 編寫複雜問題時困難。

兩者關係

1) 遞歸中必定有迭代,可是迭代中不必定有遞歸,大部分能夠相互轉換。

2) 能用迭代的不用遞歸,遞歸調用函數,浪費空間,而且遞歸太深容易形成堆棧的溢出./*相對*/

舉例以下:

[cpp]  view plain copy
 
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. //迭代實現斐波那契數列  
  5. long fab_iteration(int index)  
  6. {  
  7.     if(index == 1 || index == 2)  
  8.     {  
  9.         return 1;  
  10.     }  
  11.     else  
  12.     {  
  13.         long f1 = 1L;  
  14.         long f2 = 1L;  
  15.         long f3 = 0;  
  16.         for(int i = 0; i < index-2; i++)  
  17.         {     
  18.             f3 = f1 + f2; //利用變量的原值推算出變量的一個新值  
  19.             f1 = f2;  
  20.             f2 = f3;  
  21.         }  
  22.          return f3;  
  23.     }  
  24. }  
  25.   
  26. //遞歸實現斐波那契數列  
  27.  long fab_recursion(int index)  
  28.  {      
  29.     if(index == 1 || index == 2)  
  30.     {  
  31.         return 1;  
  32.     }  
  33.     else  
  34.     {  
  35.         return fab_recursion(index-1)+fab_recursion(index-2);    //遞歸求值  
  36.     }  
  37. }  
  38.   
  39. int main(int argc, char* argv[])  
  40. {  
  41.     cout << fab_recursion(10) << endl;  
  42.     cout << fab_iteration(10) << endl;  
  43.     return 0;  
  44. }  
相關文章
相關標籤/搜索