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