這周看了一道求數組排列的題目,解法用了遞歸,看懂之後自己對遞歸的理解更深了。
遞歸的定義
遞歸是指程序調用自身,但調用時必須改變調用參數,直到某個參數滿足退出條件。函數調用的過程會用到run-time stack,遞歸時棧中的內容有相似性,但是每一層的差異最終會導致運行棧增長的停止,並且從棧頂返回。
理解遞歸,最終還是要歸結到理解函數調用過程中運行棧的增長和退出。
run-time stack
函數P調用函數Q時,棧頂增長,棧頂的地址向低地址方向移動,寄存器%rsp的值減少。當Q中的代碼遇到return子句或者代碼全部運行之後Q返回,棧頂退出,函數P恢復調用Q之前的狀態,接着運行。
代碼演示和解釋
#include <stdio.h>
void recursive_ill(int *x, int level) {
if (level == 0) return;
for (int i = 0; i < 10; i++) {
(*x)++;
recursive_ill(x, level - 1);
}
}
int main() {
int x = 0;
recursive_ill(&x, 3);
printf("%d\n", x);
return 0;
}
大家可以先自己思考一下最終打印出來的結果是多少。
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
答案就是1110。我們接下來分析一下這個結果是怎麼來的。
這個圖片就是上面那段代碼的運行時函數調用棧的形式,因爲recursive_ill(0)會馬上返回,所以沒有畫出來。
首先,main()調用recursive_ill(3),在recursive_ill(3)中,i=0,(*x)加一,
然後調用recursive_ill(2),在recursive_ill(2),i=0,(*x)加一,
然後調用recursive_ill(1),在recursive_ill(1)中,i=0,(*x)加一,
然後調用recursive_ill(0),馬上返回;
此時,recursive_ill(1)恢復,recursive_ill(1)中,i=1,(*x)加一,
然後調用recursive_ill(0),馬上返回;
。。。。。。
當在recursive_ill(1)中,i=10時,返回,
此時,recursive_ill(2)恢復,recursive_ill(2)中,i=1,(*x)加一,
然後調用recursive_ill(1),在recursive_ill(1)中,i=0,(*x)加一,
然後調用recursive_ill(0),馬上返回;
。。。。。。
當在recursive_ill(2)中,i=10時,返回,
此時,recursive_ill(3)恢復,在recursive_ill(3)中,i=1,(*x)加一,
然後調用recursive_ill(2),在recursive_ill(2),i=0,(*x)加一,
然後調用recursive_ill(1),在recursive_ill(1)中,i=0,(*x)加一,
然後調用recursive_ill(0),馬上返回;
。。。。。。
當在recursive_ill(3)中,i=10時,返回,
main()調用printf,打印出x的值。返回,程序結束運行。
總結
我們對上面那個例子的調用過程做個總結:
函數P調用函數Q,當棧頂從函數Q回退到函數P時我們說調用結束。
在上面的代碼中,main()調用recursive_ill(3),recursive_ill(3)調用recursive_ill(2),recursive_ill(2)調用recursive_ill(1),recursive_ill(1)調用recursive_ill(0)。
main()對recursive_ill(3)的調用結束時,(*x)在recursive_ill(3)中進行了10次加一,
每一次加一之後都要調用recursive_ill(2),(*x)在recursive_ill(2)中進行了10次加一,
每一次加一之後都要調用recursive_ill(1),(*x)在recursive_ill(1)中進行了10次加一,
每一次加一之後都要調用recursive_ill(0),(*x)沒有變化。
所以(*x)在recursive_ill(3)中總共進行10次加一,在recursive_ill(2)中總共進行100次加一,在recursive_ill(1)中總共進行1000次加一。
所以,main()調用recursive_ill(3)結束後,(*x)總共進行1110次加一,如果開始(*x)是0,最終(*x)的值是1110。
ps
文章裏面的圖片有點少了,請大家對文字多點耐心,理解之後肯定很有幫助。每次的文章都是希望能幫助到大家,尤其是關注我的朋友。