在网上看到了一些人在找这个Ackerman函数 ,
不知道这个函数的实际含义,首先看到了他的递归形式:
注释部分是分析后的结果.
int rackerman(int m,int n)
{
if(m==0) return n+1; //更新n值,
else
if(n==0) return rackerman(m-1,1); //分析后要入栈一次, 同时n更新为 1
else
return rackerman(m-1,rackerman(m,n-1));//要先入m-1,然后入m. 同时 n-1
}
于是我在纸上模拟了几次栈的进出,发现只用m值在栈中进进出出,而n值是不断更新的,最后返回的值也是n值的变化.
.下面是我的非递归函数:
int
myAckerman(int m , int n )
{
list < int > listM;
listM . push_back(m);
while ( ! listM . empty () )
{
m = listM . back();
listM . pop_back();
if ( ! m )
{
n = n + 1 ;
}
else if ( ! n )
{
m = m - 1 ;
n = 1 ;
listM . push_back(m);
}
else
{
n = n - 1 ;
listM . push_back(m - 1 );
listM . push_back(m);
}
}
return n;
}
在网上找到了如下的介绍,原来类似于Fibonacci数列,也是一个计算机算法的经典题 :
Ackerman函数
当一个函数及它的一个变量是由函数自身定义时,称这个函数是双递归函数。
Ackerman函数A(m,n)定义如下:
┌ 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函数却无法找到非递归的定义。
⑵. 问题解法按递归算法实现。例如回溯等。
⑶. 数据的结构形式是按递归定义的。如树的遍历, 图的搜索等。
- A(n,m)的自变量m的每一个值都定义了一个单变量函数:
- M=0时,A(n,0)=n+2
- M=1时,A(n,1)=A(A(n-1,1),0)=A(n-1,1)+2,和A(1,1)=2故A(n,1)=2*n
- M=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)= 2^n 。
- M=3时,类似的可以推出
- M=4时,A(n,4)的增长速度非常快,以至于没有适当的数学式子来表示这一函数。
- 定义单变量的Ackerman函数A(n)为,A(n)=A(n,n)。
- 定义其拟逆函数α(n)为:α(n)=min{k|A(k)≥n}。即α(n)是使n≤A(k)成立的最小的k值。
- α(n)在复杂度分析中常遇到。对于通常所见到的正整数n,有α(n)≤4。但在理论上α(n)没有上界,随着n的增加,它以难以想象的慢速度趋向正无穷大。
- A(n,m)的自变量m的每一个值都定义了一个单变量函数:
- M=0时,A(n,0)=n+2
- M=1时,A(n,1)=A(A(n-1,1),0)=A(n-1,1)+2,和A(1,1)=2故A(n,1)=2*n
- M=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)= 2^n 。
- M=3时,类似的可以推出
- M=4时,A(n,4)的增长速度非常快,以至于没有适当的数学式子来表示这一函数。
- 定义单变量的Ackerman函数A(n)为,A(n)=A(n,n)。
- 定义其拟逆函数α(n)为:α(n)=min{k|A(k)≥n}。即α(n)是使n≤A(k)成立的最小的k值。
- α(n)在复杂度分析中常遇到。对于通常所见到的正整数n,有α(n)≤4。但在理论上α(n)没有上界,随着n的增加,它以难以想象的慢速度趋向正无穷大。
下面是树形分析方法,虽然这种方法多一倍的存储,但是方法性还是有推广意义的.
来自:http://blog.sina.com.cn/s/blog_48ebca64010008yq.html