學資料結構時就知道這個概念,一直沒有研究過。
同樣乙個求階乘的函式,首先是平時我們最熟悉的版本,也就是普通遞迴版本:
對於func(5)的遞迴呼叫如下:
然後是尾遞迴版本的:
呼叫圖是這樣的:
最大的區別是:對於第一種普通遞迴,每次函式的n*f(n-1)都要等f(n-1)呼叫返回後,再做乘法返回。也就是說,直到f(n-1)返回前,變數n的值都必須儲存在棧上。
對於尾遞迴來說,函式加了乙個引數來記錄之前函式計算的結果(有點類似動態規劃有沒有?)。所以當前函式f(n,1)最終即將呼叫f(n-1,n)的時候,該棧(f(n,1)函式的棧)內的變數(比如n和cur_mul)都不再需要儲存了。
所謂的尾遞迴優化不是說尾遞迴這種寫法是一種優化方法,而是說我們的**如果使用了尾遞迴,那麼編譯器會自動將**棧中的不再需要的空間優化掉,優化指的是編譯器對尾遞迴**的優化。說明白點,如果編譯器不做其他事情,我們的尾遞迴**和普通遞迴**的效能差距不大,都是要遞迴n層的。只不過一旦編譯器識別到尾遞迴**,就會將內部遞迴的函式直接開在之前的棧上(具體會更複雜,這樣只是簡單理解原理),這樣每層遞迴都是使用同一塊棧空間,防止了遞迴層數過高爆棧的可能。最終返回的時候,會直接把最深層的函式結果一步返回給最開始呼叫的函式。(實際上就是變成了迴圈!不再是遞迴了!)
1.尾遞迴,比線性遞迴多乙個引數,這個引數是上一次呼叫函式得到的結果;
所以,關鍵點在於,尾遞迴每次呼叫都在收集結果,避免了線性遞迴不收集結果只能依次展開消耗記憶體的壞處。
什麼是尾遞迴? - frankie楊的回答 - 知乎
2.由於尾遞迴呼叫發生在函式末尾,它自己的棧幀中已經沒有需要被使用的東西了,也就可以讓下次遞迴呼叫直接覆蓋使用當前的棧幀。
這樣造成的結果就是尾遞迴在優化後,call / ret 其實被消除了(因為直接使用當前棧幀,不需要壓棧和出棧,函式體一般也能內聯),生成的機器碼和迴圈是一樣的。
什麼是尾遞迴? - 孫竟的回答 - 知乎
敏捷到底是什麼?
文 ivar jacobson 在支援軟體工程 比如rational統一過程rup 與敏捷陣營 比如scrum或是xp 之間,人們一直存在著衝突。也不難理解,因為這兩種方法間都是在用著彼此並不相容的方式來描述的。其實大可不必,因為他們背後的觀點全然是相輔相成的。關鍵在於該如何用對兩者來說都公平的方式...
我們到底是什麼?
我們到底是什麼?我們是一種生物電流 生物電流有幾種狀態,喜怒哀樂等,可以根據外部環境進行自我切換 該種生物電流附屬在一種器官硬體上面 我們可以從器官硬體上感知一些資訊,產生新的資訊生物電流,新產生的生物電流符合原先的標準 我們可以把資訊電流儲存在器官硬體上,但具體如何儲存等資訊無法被我們感知 我們的...
SDN到底是什麼
sdn到底是什麼?雖然這個概念已經被炒到了,但還沒有人對其給出乙個明確的概念。盛科網路總監張衛峰撰寫了自己關注sdn以來,對其認識的四個階段,最後乙個階段又回到了sdn字面的意思軟體定義網路,每個階段作者的新觀點,也會給我們帶來一些啟發。以下為原文 我對sdn的認識可以分為四個階段,最後乙個階段是在...