js尾遞歸函數


 

普通遞歸:

function fac(n) {
  if (n === 1) return 1;
  return n * fac(n - 1);
}

fac(5) // 120

這是個階乘。但是占用內存,因為:

fac(5)

(5*fac(4))

(5*(4*fac(3)))

(5*(4*(3*fac(2))))

(5*(4*(3*(2*fac(1)))))

(5*(4*(3*2)))

(5*(4*(6)))

(5*24)

120

這里需要講明的是: 函數調用會產生“調用記錄(存儲着函數的相關信息)”存放在棧中,當有函數返回,對應的調用記錄才會消失,

         上述用普通遞歸實現的階乘的執行過程中,不斷的調用自身,導致一直沒有返回,這樣也就不斷的在棧中存儲調用記錄

         而當調用自身的次數過多后,就會產生我們常說的“棧溢出”

擬人描述: 就想一個人不斷地借錢(調用自身,不斷向棧中存調用記錄),但是總想着以后再還(一直沒有返回),

     當外債積累到超出自己償還能力的時候,就跑路了(棧溢出)

 

尾遞歸

function fac(n, total) {
  if (n === 1) return total;
  return fac(n - 1, n * total);
}

fac(5, 1) // 120

執行過程如下:

fac(5,1)

fac(4,5)

fac(3,20)

fac(2,60)

fac(1,120)

說明:永遠只有一個調用記錄,調用函數產生一個調用記錄,最后一步操作 return fac(n - 1, n * total) 

   把當前函數的計算結果當做參數傳遞給了下一個自身調用,這樣第一個函數調用產生的調用記錄就消失了,因為它執行完了

   依次類推,就不會溢出

尾遞歸:函數的最后一步是執行一個函數

參考來自:阮老師  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM