遞歸與迭代

轉載自https://blog.csdn.net/laoyang360/article/details/7855860

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

1.概念區分

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

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

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

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

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

遞歸分爲兩個階段:

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

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

利用遞歸可以解決很多問題:如揹包問題,漢諾塔問題,...等.

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

Tips: 由於遞歸引起一系列的函數調用,並且有可能會有一系列的重複計算,遞歸算法的執行效率相對較低.

迭代:利用變量的原值推算出變量的一個新值.如果遞歸是自己調用自己的話,迭代就是A不停的調用B.
假如現在我們不考慮編程,我們僅僅看一下使用遞歸和迭代求1+2+3…+n的過程。

使用遞歸:

sum(5)
5+sum(4)
5+4+sum(3)
5+4+3+sum(2)
5+4+3+2+sum(1)
5+4+3+2+1+sum(0)
5+4+3+2+1+0
5+4+3+2+1
5+4+3+3
5+4+6
5+10
15

使用迭代

0+1=1
1+2=3
3+3=6
6+4=10
10+5=15

上面兩個計算過程所需的步驟都是O(n)。但是兩個計算過程的形狀不一樣。

遞歸過程是一個先逐步展開(遞推)而後收縮(迴歸)的形狀,在展開階段,這一計算過程構造起一個推遲進行的操作所形成的的鏈條(這裏是+),在收縮階段纔會實際執行這些操作。這種類型的計算過程由一個推遲執行的運算鏈條刻畫,稱爲一個遞歸計算過程。要執行這種計算過程,就需要維護以後將要執行的操作的軌跡。在計算1+2+3+…+n時,推遲執行的加法鏈條的長度就是爲了保存其軌跡需要保存的信息量,這個長度隨着n值而線性增長,這樣的過程稱爲線性遞歸過程。

迭代過程的形成沒有任何增長或收縮。對於任意一個n,在計算的每一步,我們需要保存的就只有i,ret,這個過程就是一個迭代計算過程。一般來說,迭代計算過程就是那種其狀態可以用固定數目的狀態變量描述的結算過程。在計算1+2+…+n時,所需的計算步驟與n成正比,這種過程稱爲線性迭代過程。

2.辯證看遞歸和迭代

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

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

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

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

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

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

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

因而,“能不用遞歸就不用遞歸,遞歸都可以用迭代來代替”這樣的理解,還是辯證的來看待,不可一棍子打死。*/

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章