遞歸有兩個階段:遞推與回歸。
遞推:在遞推階段每一個遞歸調用通過進一步調用自己來記住這次遞歸過程。當其中有調用滿足終止條件時,遞推結束。
回歸:函數調用已逆序的方式回歸,直到最初調用的函數返回為止,此時遞歸過程結束。
基本上來說,一個程序由4個區域組成:代碼段、靜態數據區、堆與棧。代碼段包含程序運行時所執行的機器指令。靜態數據區包含在程序生命周期都一直存在的數據,不如全局變量和靜態局部變量。堆包含程序運行時動態分配的空間,比如malloc。棧包含函數調用的信息。如下圖所示:
下面是一個使用遞歸計算階乘的例子:
int fact(int n){ if (n < 0) { return 0; } else if (n == 0 || n == 1) { return 1; } else { return n * fact(n - 1); }}為了解決普通遞歸需要相當大的空間來保存函數信息,提出了尾遞歸的遞歸方式。
當遞歸調用是整個函數中最后執行的語句且它的返回值不屬于表達式的一部分時,這個遞歸調用就是尾遞歸的。
當編譯器檢查到一個函數是尾遞歸的時候,它就會覆蓋當前活躍記錄而不是在棧中去創建一個新的,這樣就解決了普通遞歸函數占用??臻g過大的問題。
使用尾遞歸修改上面的列子:
int facttail(int n, int a){ if (n < 0) { return 0; } else if (n == 0 || n == 1) { return a; } else { return facttail(n - 1, n * a); }}新聞熱點
疑難解答