ES6 入門系列 (三) 尾遞歸

  遞歸咱們不陌生,函數

  那什麼是尾遞歸呢?優化

  爲何要用尾遞歸呢?spa

  尾遞歸怎麼用呢?code

  帶着這三個問題咱們來了解它,blog

咱們知道遞歸很是耗費內存,一不當心就會發生‘棧溢出’, 相信你必定遇到過這個錯誤: stack overflow,遞歸

尾遞歸就是用來優化遞歸的這個問題的。內存

  尾遞歸的定義: 在函數的最後一步返回自身,也就是顯示地return自身就稱爲尾遞歸。對於尾遞歸來講,io

因爲只存在一個調用幀,因此永遠不會發生‘棧溢出’。console

  咱們來舉例說明尾遞歸的好處:function

  • 好比計算n的階乘, 咱們首先想到找規律, n的階乘等於n* (n-1)的階乘
  • 找出口1的階乘等於1
  • 而後咱們就很天然的用遞歸寫出
  • function jieCheng(n) {
        if (n===1) {
            return 1
        }
        return n * jieCheng(n -1);
    }
    const result = jieCheng(5);
    
    console.log(result);  // 120

    很天然, so easy有木有,

   but,  這樣咱們每遞歸一次,上一次的調用記錄還保存着, 也就是說咱們計算n的階乘最多要保存n個調用記錄,複雜度爲O(n).

   改爲尾遞歸:

   

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

console.log(weiJieCheng(5), 'wei'); // 120

  把中間變量改寫成函數的參數, 這樣就只保存了一個調用記錄,複雜度爲O(1)。

  再用蹦牀函數對尾遞歸進行優化,把遞歸執行轉換成循環執行:

function trampoline(f) {
    while(f && f instanceof Function) {
         f = f ();
    }      
}
trampoline(weiJieCheng(5, 1))
相關文章
相關標籤/搜索