在网上看到了一些人在找这个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