一.例子(用從C++描述):
行號 程序
0 p (int w)
1 {if( w>o)
2 { cout<<w;
3 p(w-1);
4 p(w-1);
5 }
6 }
結束
執行語句 p(4) 後的打印結果:4 3 2 1 1 2 1 1 3 2 1 1 2 1 1
二.說明:
1.遞歸調用與普通的調用原理相同,只不過是每次調用的函數都是自己本身。
2.我們完全可以自己編程設置堆棧(用戶堆棧),來實現與“遞歸調用”相同的功能。
3. 3.在“遞歸調用”時,系統會自動設置和管理堆棧(系統堆棧),而
無需我們的干預,但這同時增加了“遞歸調用”的神祕性。爲了更好
地 地理解“遞歸調用”,現將系統堆棧以表格的方式表示出來。
4.對於“堆棧”格式的一些說明
堆棧的格式爲:
方格a |
方格b |
方格c |
函數調用完返回的行號 |
調用的函數 |
W 的值 |
每調用一次函數就“入棧”一次;函數執行完了,就“出棧”一次
三.程序解釋:
1.開始調用p(4),此時執行的語句有:1、2、3
結束 |
P(4) |
4 |
執行p(4)的語句2:cout<<w;打印4(這是第一個結果)
但是由於語句3,在執行過程中還要調用p(3),只有p(3)執行完了,才能繼續執行p(4)。
2.開始調用P(3),此時執行的語句有:1、2、3
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
當p(3)執行完了,就會執行p(4)中的語句4(所以在方格a中,填“4”)。
執行p(3)的語句2:cout<<w; 打印3(這是第二個結果)
同上面的情況相同,當執行到語句3,還要調用p(2),只有p(2)執行完了,才能繼續執行p(3)。
3.開始調用P(2),此時執行的語句有:1、2、3
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
執行p(2)的語句2:cout<<w;打印2(這是第三個結果)
同上面的情況相同,當執行到語句3,還要調用p(1),只有p(1)執行完了,才能繼續執行p(2)。
4.開始調用P(1),此時執行的語句有:1、2、3
4 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
執行p(2)的語句2:cout<<w;打印1(這是第四個結果)
同上面的情況相同,當執行到語句3,還要調用p(0),只有p(0)執行完了,才能繼續執行p(1)。
5.開始調用P(0),此時執行的語句有:1
4 |
P(0) |
0 |
4 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
因爲w=0不滿足語句1,所以直接跳到語句5、6,從而p(0)執行完畢,p(0)要進行“出棧”操作。
6.此時執行的語句有:4
4 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
由於p(0)執行完成,且p(0)的方格a中爲4,因此繼續執行p(1)的語句4 :p(w-1); 又由於p(1)方格c中w值爲1,所以調用p(0)。
7.開始調用p(0)
5 |
P(0) |
0 |
4 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
當p(0)執行完了,就會執行p(1)中的語句5(所以在方格a中,填“5”)。
因爲w=0不滿足語句1,所以直接跳到語句5、6,從而p(0)執行完畢,p(0)要進行“出棧”操作。
8.此時執行的語句有:5
4 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
由於p(0)執行完成,且p(0)的方格a中爲5,因此繼續執行p(1)的語句5 (最後一句),所以p(1)執行完畢,p(1)要進行“出棧”操作。
9.
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
由於p(1)執行完成,且p(1)的方格a中爲4,因此繼續執行p(2)的語句4 :p(w-1); 又由於p(2)方格c中w值爲2,所以調用p(1)。
10.開始調用P(1),此時執行的語句有:1、2、3
5 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
當p(1)執行完了,就會執行p(2)中的語句5(所以在方格a中,填“5”)。
執行p(1)的語句2:cout<<w;打印1(這是第五個結果)
當執行到語句3,還要調用p(0),只有p(0)執行完了,才能繼續執行p(1)。
11.始調用P(0),此時執行的語句有:1
4 |
P(0) |
0 |
5 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
因爲w=0不滿足語句1,所以直接跳到語句5、6,從而p(0)執行完畢,p(0)要進行“出棧”操作。
12.此時執行的語句有:4
5 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
由於p(0)執行完成,且p(0)的方格a中爲4,因此繼續執行p(1)的語句4 :p(w-1);又由於p(1)方格c中w值爲1,所以調用p(0)。
13.開始調用p(0)
5 |
P(0) |
0 |
5 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
當p(0)執行完了,就會執行p(1)中的語句5(所以在方格a中,填“5”)。
因爲w=0不滿足語句1,所以直接跳到語句5、6,從而p(0)執行完畢,p(0)要進行“出棧”操作。
14.此時執行的語句有:5
5 |
P(1) |
1 |
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
由於p(0)執行完成,且p(0)的方格a中爲5,因此繼續執行p(1)的語句5 (最後一句),所以p(1)執行完畢,p(1)要進行“出棧”操作。
15.
4 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
由於p(1)執行完成,且p(1)的方格a中爲5,因此繼續執行p(2)的語句5 (最後一句),所以p(2)執行完畢,p(2)要進行“出棧”操作。
注意:其實步驟10~15重複了步驟4~9,因爲它們都調用的P(1)
16.
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
由於p(2)執行完成,且p(2)的方格a中爲4,因此繼續執行p(3)的語句4 :p(w-1); 又由於p(3)方格c中w值爲3,所以調用p(2)。
17.開始調用P(2),此時執行的語句有:1、2、3
5 |
P(2) |
2 |
4 |
P(3) |
3 |
結束 |
P(4) |
4 |
當p(2)執行完了,就會執行p(3)中的語句5(所以在方格a中,填“5”)。
執行p(2)的語句2:cout<<w;打印2(這是第六個結果)
同上面的情況相同,當執行到語句3,還要調用p(1),只有p(1)執行完了,才能繼續執行p(2)。
18.開始調用p(1)
省略……
注意:其實步驟17~29重複了3~15,因爲它們都調用的P(2)
在這步驟中,又打印了2 1 1(見步驟3、4、10)
四.結論與分析:
步驟 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
結果 |
4 |
3 |
2 |
1 |
1 |
2 |
1 |
1 |
3 |
2 |
1 |
1 |
2 |
1 |
1 |
第5個結果重複第4個結果,這是因爲他們都調用了p(1)
第6、7、8個結果重複第3、4、5個結果,這是因爲他們都調用了p(2)
第9~15個結果重複第2~8個結果,這是因爲他們都調用了p(3)