遞歸
基本遞歸:
一種強大的方法,允許一個問題以其自身越來越小的形式定義自己。在計算機科學領域,我們通過使用遞歸函數來解決帶有遞歸性質的問題,也就是用函數調用自身。
基本遞歸:例如以遞歸方式求一個數的階乘
#include<stdio.h>
int fact(int n) {
if (n < 0)
return 0;
else if (n == 0)
return 1;
else if (n == 1)
return 1;
else
return n*fact(n - 1);
}
int main() {
int a;
printf("請輸入一個值:\n");
scanf("%d", &a);
int sum;
sum = fact(a);
printf("這個值的階乘結果是%d\n", sum);
system("pause");
}
理解遞歸究竟是如何工作的,有必要先看看C語言中函數的執行的方式。基於這點,我們需要了解關於C程序在內存中的組織方式。基本上來說一個可執行程序由4個區域組成;代碼段,靜態數據區,堆與棧。
代碼段包含程序運行所執行的機器指令。
靜態數據區包含在程序生命週期內一直持久的數據,比如全局變量和靜態局部變量。
堆包含程序運行時時態分配的存儲空間,比如用malloc分配的內存。
棧包含函數調用的信息。按照慣例,堆的增長方向從程序低地址到高地址向上增長,而棧的增長方向剛好相反(實際情況可能不是這樣,與CPU的體系結構有關)。
當C程序中調用了一個函數時,棧中會分配一塊空間來保存與這個調用相關的信息。每一個調用都被當做是活躍的。棧上的那塊存儲空間稱爲活躍記錄,或者稱爲棧幀。
棧幀由5個區域組成:輸入參數,返回值空間,計算表達式時用到的臨時存儲空間,函數調用時保存的狀態信息以及輸出參數。(輸入參數是傳遞到活躍記錄中的參數:輸出參數是傳遞給活躍記錄中調用的函數所使用的。一個活躍記錄中的輸出參數就成爲棧中下一個活躍記錄的輸入參數,函數調用產生的活躍記錄將一直存在於棧中直到這個函數調用結束)