遞歸調用效率問題,遞歸與循環比較

1.所謂的遞歸慢到底是什麼原因呢?

大家都知道遞歸的實現是通過調用函數本身,函數調用的時候,每次調用時要做地址保存,參數傳遞等,這是通過一個遞歸工作棧實現的。具體是每次調用函數本身要保存的內容包括:局部變量、形參、調用函數地址、返回值。那麼,如果遞歸調用N次,就要分配N*局部變量、N*形參、N*調用函數地址、N*返回值。這勢必是影響效率的。

 

2.用循環效率會比遞歸效率高嗎?

遞歸與循環是兩種不同的解決問題的典型思路。當然也並不是說循環效率就一定比遞歸高,遞歸和循環是兩碼事,遞歸帶有棧操作,循環則不一定,兩個概念不是一個層次,不同場景做不同的嘗試。

2.1遞歸算法:

優點:代碼簡潔、清晰,並且容易驗證正確性。(如果你真的理解了算法的話,否則你更暈)

缺點:它的運行需要較多次數的函數調用,如果調用層數比較深,需要增加額外的堆棧處理(還有可能出現堆棧溢出的情況),比如參數傳遞需要壓棧等操作,會對執行效率有一定影響。但是,對於某些問題,如果不使用遞歸,那將是極端難看的代碼。

2.2循環算法:

優點:速度快,結構簡單。

缺點:並不能解決所有的問題。有的問題適合使用遞歸而不是循環。如果使用循環並不困難的話,最好使用循環。

2.3遞歸算法和循環算法總結:

1. 一般遞歸調用可以處理的算法,也通過循環去解決常需要額外的低效處理。

2. 現在的編譯器在優化後,對於多次調用的函數處理會有非常好的效率優化,效率未必低於循環。

3.遞歸和循環兩者完全可以互換。如果用到遞歸的地方可以很方便使用循環替換,而不影響程序的閱讀,那麼替換成遞歸往往是好的。(例如:求階乘的遞歸實現與循環實現。)

 

3.那麼遞歸使用的棧是什麼樣的一個棧呢?

首先,看一下系統棧和用戶棧的用途。

3.1系統棧(也叫核心棧、內核棧)是內存中屬於操作系統空間的一塊區域,其主要用途爲: (1)保存中斷現場,對於嵌套中斷,被中斷程序的現場信息依次壓入系統棧,中斷返回時逆序彈出; (2)保存操作系統子程序間相互調用的參數、返回值、返回點以及子程序(函數)的局部變量。

3.2用戶棧是用戶進程空間中的一塊區域,用於保存用戶進程的子程序間相互調用的參數、返回值、返回點以及子程序(函數)的局部變量。

我們編寫的遞歸程序屬於用戶程序,因此使用的是用戶棧。


4.遞歸調用過多導致的棧溢出


例子:劍指offer中題目五 從尾到頭打印鏈表 用遞歸實現

          當鏈表很長時,遞歸層級過深,可能導致棧溢出

那麼過多的遞歸調用爲什麼會引起棧溢出呢?事實上,函數調用的參數是通過棧空間來傳遞的,在調用過程中會佔用線程的棧資源。而遞歸調用,只有走到最後的結束點後函數才能依次退出,而未到達最後的結束點之前,佔用的棧空間一直沒有釋放,如果遞歸調用次數過多,就可能導致佔用的棧資源超過線程的最大值,從而導致棧溢出,導致程序的異常退出。

發佈了42 篇原創文章 · 獲贊 7 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章