對遞歸的進一步理解

這周看了一道求數組排列的題目,解法用了遞歸,看懂之後自己對遞歸的理解更深了。

遞歸的定義

遞歸是指程序調用自身,但調用時必須改變調用參數,直到某個參數滿足退出條件。函數調用的過程會用到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

文章裏面的圖片有點少了,請大家對文字多點耐心,理解之後肯定很有幫助。每次的文章都是希望能幫助到大家,尤其是關注我的朋友。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章