尾遞歸和一般的遞歸不同在對記憶體的占用,普通遞歸建立stack累積而後計算收縮,尾遞歸隻會占用恒量的記憶體(和疊代一樣)。
遞歸是指函數直接或間接地調用自己。
(普通遞歸) :
function f(x) {
if (x === ) return ;
return + f(x-);
}
尾遞歸的判斷标準是函數運作【最後一步】是否調用自身,而不是是否在函數的【最後一行】調用自身。
尾遞歸
function f(x) {
if (x === ) return ;
return f(x-);
}
使用尾遞歸可以帶來一個好處:因為進入最後一步後不再需要參考外層函數(caller)的資訊,是以沒必要儲存外層函數的stack,遞歸需要用的stack隻有目前這層函數的,是以避免了棧溢出風險。
尾遞歸優化主要是對棧記憶體空間的優化, 這個優化是O(n)到O(1)的; 至于時間的優化, 其實是由于對空間的優化導緻記憶體配置設定的工作減少所産生的, 是一個常數優化, 不會帶來質的變化.
尾遞歸形式和循環(或者說”疊代”)形式大緻就是同一個邏輯的兩種表達形式而已. 經過尾遞歸優化的尾遞歸代碼和循環的代碼的執行效率基本上是相當的. 這也是函數式程式設計效率上沒有落後的一個很重要的原因.