函式中有直接或間接地呼叫自身函式的語句,這樣的函式稱為遞迴函式。遞迴函式用
得好,可簡化程式設計工作。但函式自己呼叫自己,有可能造成死迴圈。為了避免死迴圈,要
做到兩點:
(1) 降階。遞迴函式雖然呼叫自身,但並不是簡單地重複。它的實參值每次是不一樣
的。一般逐漸減小,稱為降階。如教科書式(33)的ackerman 函式,當m≠0 時,求
ack(m,n)可由ack(m-1,⋯)得到,ack()函式的第1 個引數減小了。
(2) 有出口。即在某種條件下,不再進行遞迴呼叫。仍以教科書式(33)的ackerman
函式為例,當m=0 時,ack(0,n)=n+1,終止了遞迴呼叫。所以,遞迴函式總有條件語
句。m=0 的條件是由逐漸降階形成的。如取ack(m,n)函式的實參m=-1,即使通過降階也
不會出現m=0 的情況,這就造成了死迴圈。
編譯軟體在遇到函式呼叫時,會將呼叫函式的實參、返回位址等資訊存入軟體自身所
帶的棧中,再去執行被調函式。從被調函式返回時,再將呼叫函式的資訊出棧,接著執行
呼叫函式。編譯軟體開闢的棧空間是有限的,當遞迴呼叫時,巢狀的層次往往很多,就有
可能使棧發生溢位現象,從而出現不可預料的後果。執行algo3-8.cpp 時,m、n 的取值就
不可過大。
// algo3-8.cpp 用遞迴呼叫求ackerman(m,n)的值**執行結果:#includeint ack(int m,int n)
void main()
/*please input m,n:3,9
ack(3,9)=4093
press any key to continue
*/
// algo3-9.cpp 用遞迴函式求解迷宮問題(求出所有解)**執行結果如下:#include"c1.h" // 根據《pascal程式設計》(鄭啟華編著)中的程式改編
#include"func3-1.cpp" // 定義牆元素值為0,可通過路徑為-1,通過路徑為足跡
void try(postype cur,int curstep)
,,,}; // ,移動方向,依次為東南西北
for(i=0;i<=3;i++) // 依次試探東南西北四個方向
m[next.x][next.y]=-1; // 恢復為通路,以便在另乙個方向試探另一條路
curstep--; // 足跡也減1
} }}void main()
此迷宮從入口到出口有2 條路徑。由入口(1 行1 列足跡1)處向4 個方向試探,只有2
個方向(東、南)是通路(-1)。首先朝東繼續試探。足跡2~4 都只有1 個方向是通路,足
跡5 到達出口。輸出路徑且逐一恢復足跡為-1(通路)。恢復後的情況是除入口為1 外,迷
宮其它各點與初態相同,以便第2 條路徑(由入口向南)繼續試探。
// algo3-10.cpp hanoi塔問題,呼叫演算法3.5的程式**執行結果如下:#includeint c=0; // 全域性變數,搬動次數
void move(char x,int n,char z)
void hanoi(int n,char x,char y,char z) // 演算法3.5
}void main()
/*3個塔座為a、b、c,圓盤最初在a座,借助b座移到c座。請輸入圓盤數:3
第1步: 將1號盤從a移到c
第2步: 將2號盤從a移到b
第3步: 將1號盤從c移到b
第4步: 將3號盤從a移到c
第5步: 將1號盤從b移到a
第6步: 將2號盤從b移到c
第7步: 將1號盤從a移到c
press any key to continue
*/
棧與遞迴(Hanoi塔問題)
今天上午上課時,再看了下hanoi塔的問題,其中對遞迴的分析,讓自己對遞迴呼叫有了更深一步地理解,把書上的 實現一下,然後分析其遞迴工作棧的狀態,理解了以後,會讓自己受益頗多。學習,不能只看著別人是怎麼寫的,自己就照著寫,這是非常不對的,你要分析別人為什麼這樣寫,你要懂得的是思路,而不僅僅是答案。1...
hanoi塔問題的遞迴實現
一 背景故事 二 問題描述 假設有x,y,z三座塔座。在塔座x上有n個直徑各不相同 依次從小到大的編號為1,2.n的圓盤。現要求將x座上的盤子移動到z上,移動要求如下 1 一次只能移動乙個盤子。2 盤子只能插在x,y,z的某個塔座上。3 任何時刻不能將較大的盤子壓在較小的盤子上。如何移動盤子呢?當只...
遞迴 Hanoi塔問題
題目 hanoi塔問題,遊戲規則 1 每次只能移動乙隻圓盤 2 任何時候大圓盤不能壓在小圓盤之上 3 任何時候都不允許將圓盤放在三根立軸之外的任何地方。分析 遞迴的 base case 當只有乙個圓盤的時候,直接從圓盤所在的立軸移動到目標立軸,即完成。遞迴的 recursion rule 如圖所示,...