3.3栈与递归的实现
一個直接調用自己或通過一系列的調用語句間接地調用自己的函數(shù),稱為遞歸函數(shù)。
(先說明下若在函數(shù)A中調用了函數(shù)B,則稱函數(shù)A為調用函數(shù),函數(shù)B為被調用函數(shù))
當一個函數(shù)的運行期間調用另一個函數(shù)時,在運行被調用的函數(shù)之前,系統(tǒng)要完成3件事情
1.將所有的實參、返回地址等信息傳遞給被調用的函數(shù)保存。
2.為被調用函數(shù)的局部變量分配存儲區(qū)。
3.將控制轉移到被調用函數(shù)入口。
被調用函數(shù)返回調用函數(shù)之前也要完成3件工作。
1.保存被調用函數(shù)的計算結果。
2.釋放被調用函數(shù)的數(shù)據區(qū)。
3.依照被調用函數(shù)保存的返回地址將控制轉移到調用函數(shù)。
這時要通過棧來實現(xiàn),系統(tǒng)將整個程序運行所需的數(shù)據空間安排在一個棧中,每當調用一個函數(shù)時,就為它在棧頂分配一個存儲區(qū),出棧就釋放。
圖3.6(c)主函數(shù)調用函數(shù)first,first再調用second
圖3.6(a)當前正在執(zhí)行函數(shù)second中某個語句時棧的狀態(tài)
圖3.6(b)second退出后正執(zhí)行的函數(shù)first中某個語句時棧的狀態(tài)
下面看看Hanoi塔的遞歸
下面對這個表做出解釋:
這個表第列是運行語句行號:
代碼如下:
void hanoi (int n, char x, char y, char z) { ?//?// 將塔座x上按直徑由小到大且至上而下編號為1至n的n個圓盤按規(guī)則搬到// 塔座z上,y可用作輔助塔座。// 搬動操作 move (x, n, z) 可定義為:// ? (c是初值為0的全局變量,對搬動計數(shù))// ? printf("%i. Move disk %i from ?%c ?to ?%c\n", ++c, n, x, z);1 2? if (n==1) 3? ? move(x, 1, z); ? ? ? ?//將編號為1的圓盤從x移到z 4? else { 5? ? hanoi(n-1,x,z,y); 6? ? move(x, n, z); ? ? ? ?//將編號為n的圓盤從x移到z 7? ? hanoi(n-1, y, x, z); ?//將y上編號為1至n-1的圓盤移到z,x作輔助塔 8? } 9}
下面分析下代碼和過程:
首先說明下,遞歸代碼是非常巧妙的,基本上大家知道這個程序就可以了,考研的學生知道下原理,然后背下來,這個東西一般人是寫不出的。
下面來說明下思路,這個算法的巧妙之處在于他用了幾行的代碼實現(xiàn)了Hanoi塔(感覺是廢話)。
1.在第五步時,遞歸工作棧狀態(tài)為 8,1,c,a,b
這個8是返回第八行,1,是第一塊行,c,a,b,是把c移到b,并且a為輔助,那么為什么是1,c,a,b,這個1是因為第二塊圓盤第6步執(zhí)行完成后,第5部的時候第二塊圓盤把x,z,y(也就是a,c,b)給了hanoi的參數(shù),這樣的話x=a,y=c,z=b,在第7步時就是c,a,b了。
整個hanoi的代碼上難點就在這,基本上這個大家理解下思路,會了這個思路過程就可以了。
總結
以上是生活随笔為你收集整理的3.3栈与递归的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 略谈float
- 下一篇: 7.3图的遍历(深度优先)-理论