阿克曼函数的c语言,C语言,关于阿克曼函数非递归实现的一点拙见
第一次寫博客,初學數據結構,以下是我對阿克曼函數非遞歸實現的一點拙見,有錯誤的地方,歡迎大家批評指教。
1.初識阿克曼函數
我們先來看看阿克曼函數的形式
已知Ackerman函數的定義如下:
n+1 m=0
akm(m, n) = akm(m-1, 1) m≠0,n=0
akm(m-1, akm(m, n-1) m≠0,n≠0
阿克曼函數是以遞歸的形式給出的,采用遞歸算法解決這個問題是很直接的
//Ackerman 遞歸實現算法
ElemTypy Ackerman(ElemType m,ElemType n)
{//輸入m,n的值,返回函數結果值
if(m == 0) result = n+1;
else if(m != 0 && n == 0) result = Ackerman(m-1,1);
else result = Ackerman((m-1,Ackerman(m,n-1)));
return result;
}//Ackerman
2.阿克曼函數的非遞歸實現
我認為,要想完成阿克曼函數的非遞歸實現,有三點十分重要。
①.要清楚阿克曼函數的遞歸算法,本質上是是如何實現的,了解之后我們發現,遞歸的本質,是用系統的棧存儲了遞歸過程產生的地址和變量。
②.了解到遞歸的本質之后,我們就可以設想,自己建立一個棧,手動(用自定義函數) 來實現入棧和出棧操作。
③.當我們想到用自己建立的棧去實現非遞歸時,緊接著的問題就是,用這個棧去存儲什么內容? 要想解決這個問題,我們需要仔細研究阿克曼函數本身,研究之后,我們發現,函數的出口,在“m = 0”時,輸出的是值“n+1”,我覺得看到這一點對于理解下面的非遞歸實現代碼非常重要。
我們還可以發現,輸入一個m,n,要求得函數值,不過是m,n不停地變化,不停地帶入,一層一層求解,最終再返回到我們要求的問題的過程,于是建立兩個存儲m,n的值的棧的思想就萌生了。
我們來重點理解一下非遞歸實現的算法:
int Ackerman(int m,int n) /函數的返回值是整型,也就是 我們前面提到的出口“n+1”的值/
{
STACK S,T; //建立兩個棧S,T,分別用來存儲m,n的值
S = InitStack();
T = InitStack();
Push(&S,m);
Push(&T,n); /將輸入的m,n值壓入棧,怎么更好的理解把這兩個數壓入棧到底是什么意思呢? 我的理解是,把這兩個數壓入棧就像是向輸入計算機輸入你要求的問題,計算機把這兩個數存起來,然后按照程序執行,如果可以得到結果(比如m=0的情形),那就回答你的問題,并且清除你輸入的參數,如果不能直接解決,那就先保留這兩個數,然后走到下一步程序,看能不能解決,如果能解決,那就返回結果給上一層,如果不能保留,就繼續往下走,問題走到盡頭的時候,一定會得到解決,再一層一層得返回結果,最終求得問題的答案/
while(StackEmpty(&S)) /當棧不為空時,進行循環/
{
while(m != 0)
{
if(n == 0)
{ //m!=0 && n == 0 的情況
m = m-1;
n = 1;
Push(&S,m);
Push(&T,n); /將改變后的m,n值壓入棧/
}
else
{
n = n-1;
Push(&S,m-1);
Push(&T,-1); /這一步是m,n都不為0的情況,非常特殊,因為這一步是一個雙遞歸的過程,我們要向走通這一步,就要先解決最內層的遞歸,然后再解決外層遞歸,為此,我們將m-1壓入S棧,-1壓入T棧,-1是一個標志,用來標識這種特殊情況。 我們還發現,這一步我們把n復制為n-1,但是沒有對m重新賦值,這也是為了要求先求出內層遞歸的值akm(m, n-1),當求出這個值之后,我們用求得的值賦把T棧中該位置的-1替換掉,就成功走通這一步啦!/
}
}
n = n+1; /當m等于0時,按照函數法則執行,給n賦值n+1/
while(StackEmpty(&S) && *(T.top-1) != -1)
{
Pop(&S);
Pop(&T);
}/這一步可以和我上面提到的情況特殊那一步聯系起來,當你最終求得akm(m, n-1)時(其實也就是求得的T棧中-1位置本應該壓入的n的值),我們的目的達到了,就可以把S,T棧中沒用的信息全都彈出,回到我們要解決的問題的位置/
if(StackEmpty(&S))
{
m = *(S.top-1);
Pop(&T);
Push(&T,n);
}/但我們回到了我們要解決的問題的位置(把-1壓入棧的位置),由于我們再計算內層遞歸的時候,改變了m的值,這里我們把m賦值為我們之前把-1壓入T棧的同時,壓入S棧的“m-1”,也就是此時S棧的棧頂元素/
}
return n; /*當整個循環完成時,返回n的值,就是我們想要的最終答案*/
}
3.以(2,1)為例,棧的變化圖解
第一次發博客,有錯誤的地方希望大家多多指教
總結
以上是生活随笔為你收集整理的阿克曼函数的c语言,C语言,关于阿克曼函数非递归实现的一点拙见的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql的应用_mysql应用场景
- 下一篇: 哪些应用场景在使用语音连麦