棧的大小是固定的,這也就意味着不能無限的遞歸。遞歸到某些時候,棧頂將會沒有更多空間
來添加新的棧頂—就好像櫥櫃的空間被擠滿,不能增加一個盤子一樣
void recurse() { recurse(); //函數調用其自身 } int main() { recurse();//開始遞歸 } //最終 棧空間會消耗一空,程序將因棧溢出而崩潰
函數相互遞歸,以階乘為例:
int factorial_odd (int x) { if(x == 0) { return 1; } return factorial_even(x-1); } int factorial_even(int x) { if(x == 0) { return 1; } return factorial(x-1); } int factorial(int x) { if(x%2==0) { return factorial_even(x); } else { return factorial_odd(x); } } //基線條件沒有防負數輸入 ,即使調用factorial(-1)會導致這樣的 //調用棧 factorial(-1000))
遞歸需要做許多函數調用,每個函數調用都需要設置有一個棧幀,並傳遞參數,這些都增加了時間開銷,而這些開銷循環中沒有。絕大多數情況下,現代計算機
中這些開銷影響並不顯著。但如果你的代碼頻繁執行(比如短時間內執行百萬次甚至上億次),你必須關注函數調用性能的問題
遞歸比循環更加強大的地方在於,遞歸函數維持着一個保存每次遞歸調用當前狀態的棧,允許函數獲得子問題的結果后繼續處理。
遞歸算法:將問題分解成更小的版本的相同問題,從而解決問題。