關於尾呼叫和尾遞迴

2021-08-31 13:43:21 字數 1735 閱讀 1332

(1)尾呼叫:指某個函式的最後一步是呼叫另乙個函式。

例如:

function a(n)
(最後一步呼叫並不意味著在函式的尾部,只要是最後一步即可)

function a(n)

return c(n);

}

(2)什麼樣的情況不是尾呼叫

情況一:

function f(x)
解釋:呼叫g之後,還有賦值操作,故不屬於尾呼叫。

情況二:

function f(x)
解釋:也是在呼叫g之後,還有後續別的操作,故也不屬於尾呼叫。

情況三:

function f(x)
解釋:情況三相當於:

function f(x)
(3)尾呼叫的優化:(只保留記憶體函式的呼叫幀)

《1》:尾呼叫不同於其他呼叫的點在於他特殊的呼叫位置。

《2》:函式呼叫會在記憶體形成乙個「呼叫記錄」,又稱「呼叫幀」(call frame),儲存呼叫位置和內部變數等資訊。如果在函式a的內部呼叫函式b,那麼在a的呼叫幀上方,還會形成乙個b的呼叫幀。等到b執行結束,將結果返回到a,b的呼叫幀才會消失。如果函式b內部還呼叫函式c,那就還有乙個c的呼叫幀,以此類推。所有的呼叫幀,就形成乙個「呼叫棧」(call

stack)

《3》:尾呼叫由於是函式的最後一步操作,所以不需要保留外層函式的呼叫幀,因為呼叫位置、內部變數等資訊都不會再用到了,只要直接用內層函式的呼叫幀,取代外層函式的呼叫幀就可以了.

《4》:如果所有函式都是尾呼叫,那麼完全可以做到每次執行時,呼叫幀只有一項,這將大大節省記憶體。這就是「尾呼叫優化」的意義。

《5》只有不再用到外層函式的內部變數時,內層函式的呼叫幀才會取代外層函式的呼叫幀,否則無法進行尾呼叫優化。

function foo(a);

return add(a);

};

備註:上述**不會進行尾呼叫優化,因為內層函式用到了外層函式的內部變數。

(1)尾遞迴:函式呼叫自身稱為遞迴,如果尾呼叫自身,則是尾遞迴。

function tail(n) 

tail(3);

上述**的時間複雜度為o(n),最多需要儲存n個呼叫記錄;

function tail(n,total)

return tail(n-1,n*total);

}

上述**的時間複雜度為o(1),只保留乙個呼叫記錄.

(2)遞迴函式的改寫:

尾遞迴的實現,往往需要改寫遞迴函式,確保最後一步只呼叫自身。做到這一點的方法,就是把所有用到的內部變數改寫成函式的引數

備註:參考資料(es6官方教程)

尾呼叫和尾遞迴

造成這樣的結果是因為每個函式在呼叫另乙個函式的時候,沒有return該呼叫,所以執行引擎會認為你還沒有呼叫完畢,會保留呼叫幀。而如果使用尾呼叫優化,呼叫幀就永遠只有一條,這個時候就會節省很大一部分的記憶體空間,維護了 執行的流暢性。以上 就叫做尾呼叫優化,這個時候呼叫幀就永遠只有一條,節省了部分記憶...

尾呼叫 尾遞迴

首先什麼是尾呼叫呢?我的理解是在,函式的最後呼叫乙個函式,並不包含該函式的任何變數。如 def f n return g n 複製 這個就是尾呼叫,尾呼叫的乙個好處就是,不用生成呼叫棧,因為假設是個尾呼叫,那麼當我執行到函式末尾的時候,這個函式相關的資訊我都可以不用保留了,因此不會出現棧溢位的問題。...

遞迴尾呼叫

什麼是遞迴尾呼叫 遞迴呼叫放在函式結尾 區別 def fac n if n 0 return 1 else return n fac n 1 def print fa n if n 0 print fa n 1 print n print fa 10 結果 1到10def fac n if n 0 ...