Ackerman函数在许多讲解递归的书中都提到,但似乎又对解题没有太大的意义,暂时不知道了。不过这个东西,是一个数学知识点,暂时收藏于此吧。

查了一下维基百科和百度百科,表面上两个定义不一样,仔细推敲其实是一样的。(维基百科里面A(m,n)和百度百科里面A(n,m)当中的参数n、m代表含义是一样的,只是它们两个递归函数的参数的顺序写的不一样而已。)

先看Fibonacci数列

Fibonacci数列是一个非常重要,应用非常广的知识点,其递归定义如下:

(百度百科:http://baike.baidu.com/link?url=hSbCp3OLCl79y1H_fDWugAniyMFuEK7IlB2KB--g2oLAMkcWvv_3wkJRjClkq2cg)

递推公式

斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

如果设F(n)为该数列的第n项(n∈N*),那么这句话可以写成如下形式:

显然这是一个线性递推数列。

通项公式

下面看看Ackerman函数:

Fibonacci数列可以写出通项公式,就是用非递归的方式去下定义。但并非一切的递归函数都能用非递归方式去定义。下面讲一个双递归函数——Ackerman函数,它的复杂性就比Fibonacci数列递归公式要复杂多了。

百度百科Ackerman函数  (其实下面百度百科关于Ackerman函数的描述大体是抄自王晓东的《算法设计与分析(第2版)》清华大学出版社第2章递归与分治策略例题2.3 。)

当一个函数及它的一个变量是由函数自身定义时,称这个函数是双递归函数.当两个连续函数都趋于无穷时,我们常用洛必达法则来比较它们趋向无穷的快慢。函数的阶越高,它趋向无穷的速度就越快。在定义在正整数域上的函数中,n!趋向于正无穷的速度非常快,所以在算法设计中如果出现这样的时间复杂度就太糟糕了。logn趋向无穷的速度则非常慢。

今天你将看到一个增长速度比n!快的多的函数和一个比logn慢的多的函数,它们都源于一个函数–’Ackerman Function’。
 Ackerman函数有A(n,m)有两个独立的整变量m>=0,n>=0,其定义如下
A(1,0)=2;
A(0,m)=1 m>=0
A(n,0)=n+2 n>=2
A(n,m)=A(A(n-1,m),m-1) n,m>=1
A(n,m)的每一个自变量都定义了一个单变量函数。递归式的第三式定义了函数“加2”。
m=1时,由于A(1,1)=A(A(0,1),0)=A(1,0)=2
以及A(n,1)=A(A(n-1),1),0)=A(n-1,1)+2  (n>1),因此A(n,1)=2n (n>=1),即A(n,1)定义了函数“乘2”
当m=2时,由于A(1,2)=A(A(0,2),1)=A(1,1)=2
A(n,2)=A(A(n-1,2),1)=2A(n-1,2),因此A(n,2)=2^n

以此类推,,其中2的层数为n。

A(n,4)的增长速度已经变得难以想象的快,以至于不能写出一个通项公式来表示这一函数。

下面再来考虑单变量Ackerman函数A(n):=A(n,n)。 设其逆函数为B(n):=min{k|A(k)>=n},即B(n)是使n<=A(k)成立的最小k值。
由A(0)=1,A(1)=2,A(2)=4,A(3)=16推知B(1)=0,B(2)=1,B(3)=B(4)=2和B(5)=…=B(16)=3。由此可以看出B(n)的增长速度非常慢。
A(4)=222…2其中2的层数为65535,这个数有log(A(4))位。所以,对于通常所见到的正整数n,有B(n)<=4
但是理论上B(n)没有上界,随着n的增加,它将以难以想象的慢速度趋向正无穷大
Ackerman函数有A(n,m)有两个独立的整变量m>=0,n>=0,其定义如下
A(1,0)=2;
A(0,m)=1 m>=0
A(n,0)=n+2 n>=2
A(n,m)=A(A(n-1,m),m-1) n,m>=1
A(n,m)的自身变量m的每一个值都定义了一个单变量函数

维基百科:Ackerman函数的描述

定义如下:

乍一看,这个定义和上面百度百科给的定义不太一样。仔细分析,其实它们两个A()函数当中的m、n含义没变,只是参数当中顺序刚好相反而已。

下面是网友的代码:(来源:http://blog.csdn.net/gpengtao/article/details/7438587)

int ack(int m,int n)
{
if(m == )
return n+;
else if(n == )
return ack(m-,);
else
return ack(m-,ack(m,n-));
}

Ackerman函数的更多相关文章

  1. Ackerman函数的栈实现

    一.Ackerman函数: ackerman函数的定义如下: 二.Ackerman函数的递归实现: 利用递归来实现ackerman函数是比较简单的: /*Sample Input: 0 1 1 1 S ...

  2. Ackerman 函数 (双递归函数)

    public static int ackerman(int n,int m){  if(n==1&&m==0){return 2;}  else if(n==0&&m ...

  3. Ackerman 函数

    先留个简介: 函数定义: 从定义可以看出是一个递归函数.阿克曼函数不仅值增长的非常快,而且递归深度很高. 一般用来测试编译其优化递归调用的能力.. 如果用一下代码简单实现的话,输入参数4,2程序就直接 ...

  4. 最小生成树---Kruskal/Prime算法

    1.Kruskal算法 图的存贮采用边集数组或邻接矩阵,权值相等的边在数组中排列次序可任意,边较多的不很实用,浪费时间,适合稀疏图.      方法:将图中边按其权值由小到大的次序顺序选取,若选边后不 ...

  5. 并查集(UVA 1106)

    POINT: 把每个元素看成顶点,则一个简单化合物就是一条无向边,若存在环(即k对组合中有k种元素),则危险,不应该装箱,反之,装箱: 用一个并查集维护连通分量集合,每次得到一种化合物(x, y)时检 ...

  6. 数据结构之并查集Union-Find Sets

    1.  概述 并查集(Disjoint set或者Union-find set)是一种树型的数据结构,常用于处理一些不相交集合(Disjoint Sets)的合并及查询问题. 2.  基本操作 并查集 ...

  7. $\mathcal{OI}$生涯中的各种数论算法的证明

    嗯,写这个是因为我太弱了\(ORZ\). #\(\mathcal{\color{silver}{1 \ \ Linear \ \ Sieve \ \ Method \ \ of \ \ Prime}} ...

  8. 并查集 (Union-Find Sets)及其应用

    定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的 ...

  9. 栈与递归的实现(Hanoi塔问题等等)

    函数中有直接或间接地调用自身函数的语句,这样的函数称为递归函数.递归函数用 得好,可简化编程工作.但函数自己调用自己,有可能造成死循环.为了避免死循环,要 做到两点: (1) 降阶.递归函数虽然调用自 ...

随机推荐

  1. PHP中常用正则表达式大全

    常用正则表达式大全!(例如:匹配中文.匹配html) 匹配中文字符的正则表达式: [u4e00-u9fa5]    评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内 ...

  2. 在 Linux 的 KVM虚拟机 上安装 Mac OS 系统的研究总结

    在 Linux 的 KVM虚拟机 上安装 Mac OS 系统的研究总结 一.资料来源:    网上一共找到两个方法,一个是视频上的教程,一个是网页资料. 二.视频资料方法内容:1.install qe ...

  3. 如何在Apache中建立一个新端口

    环境: Windows server 2008 R2, Apache, PHP5 步骤: 建立一个目录,里面放置一个index.php. 打开Apache\conf\httpd.conf 文件,做如下 ...

  4. Qt线程(1) moveToThread

    若在Qt准备使用线程类一般有两种方式(1) 采用WorkObject配合QThread进行使用 (2)继承QThread, 重载run()函数即可. 注:采用Qt::Concurrent之类的不在本文 ...

  5. ld链接问题解决

    http://stackoverflow.com/questions/480764/linux-error-while-loading-shared-libraries-cannot-open-sha ...

  6. Java-->类的成员

    一.方法重载 在同一个类中,方法名相同.形参列表不同的两个多个方法之间构成重载!overload 调用方法的时候,是根据你传递的实参,来决定到底调用的是重载的哪个方法!!! 注意: 1.判断形参列表是 ...

  7. 一行能装逼的JavaScript代码

    一行能装逼的JavaScript代码 2016-06-28 野狗 一行神奇的JS代码,当时我就震 惊了,这不就是传说中的ZB神奇么… … 哈哈. 写本篇文章的缘由是之前看到了一段js代码,如下: (! ...

  8. SQL参数化查询--最有效可预防SQL注入攻击的防御方式

    参数化查询(Parameterized Query 或 Parameterized Statement)是访问数据库时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值. 在使用参 ...

  9. Objective-c——UI基础开发第九天(QQ好友列表)

    一.知识点: 1.双模型的嵌套使用 2.Button的对齐方式 3.优化UITableView的加载 4.layoutSubview的使用 5.cell的折叠代理 二.双模型的嵌套定义: 注意是将se ...

  10. scala言语基础学习九

    模式匹配 case _ =>不能放在函数的中间必须放在最后,否则scala会编译不通过 在case 里面使用if守卫 在模式匹配中获取输入的数据(在匹配不到的情况下) 对类型进行匹配 case ...