ackerman函数的非递归实现(递归函数非递归化)

本文介绍了阿克曼函数的递归定义及其快速指数级增长的特性,指出其在数学和计算机科学中的应用。作者通过学习汇编原理和栈实现,成功将阿克曼函数转化为非递归实现,以此作为加深理解的例子,并强调理论学习的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ackerman函数(阿克曼函数,以下简称ack函数)是一个双参数递归函数,用递归计算代码如下

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

ack函数像Dirichlet函数一样,是因为为了澄清某种概念而在数学(计算科学)史有一席之地。
ack函数最初是作为一个非线性的链式递归的例子而被提出来的,它增长很快,事实上m>3时关于n是远高于线性递推的指数级增长(关于m增长地更快)而反直觉,即使精确计算ack(4,1)也是做不到的,即使ack(3,3)也有61,如果不记忆化搜索,需要递归2000余次才可以计算出来!如果不去考虑ack(3,n)的指数增长的通项而被小数字迷惑企图直接计算,那么会算得毫无头绪,所以ack函数被广泛用于计算机预赛,笔试,数学自主招生考试中。
那么既然ack函数增长地如此之快,那么ack(m,1)的反函数增长地极其缓慢了。事实上,路径压缩的并查集经过足够久的查询,每次查询你平均复杂度就是反阿克曼函数级别的(也就是log*级别的,至于为什么,我至晚在2012年就想知道这个问题了,现在终于知道…我恐怕短时间内没法知道(~^~),算法导论里面有对此的推导,有兴趣的同学可以去看一下),好吧,这是一些有趣的冷知识,和我和ack函数的历史渊源,就当随笔写出来。
本以为我和ack的缘分在预赛题中知道它怎么做后就没有什么新进展了,最多以后讲到这个题,但是万万没想到我会以一种奇怪的方式遇到这个函数,科学史上隽永有名的函数例如Dirichlet函数,ack函数果然白发如新。


最近学习ics里的汇编原理初步和数算的栈实现递归方法,事实上这两者是相通的。我虽然没有编写过具体汇编代码,但是大概原则上知道了怎么把函数调用用堆栈实现,怎么用栈机制非递归实现递归。纸上得来终觉浅,我决定找一个例题,我编了一个复杂点的题—ackerman函数的非递归实现(递归函数非递归化)。
经过一番调试调试对了,但是人还是很懵懂,看来还要加强理论学习,不过不得不说这是个很好的例题。


int Ack(int M,int N)
{
    int top=0,m,n;
    int stack[10000][4]={{M,N}};//记录信息m,n,Ack(m,n),跳转出口种类;
    while (true)
    {
        m=stack[top][0];
        n=stack[top][1];
        if (m==0)
            stack[top][2]=n+1;
        else if (n==0)
        {
            top++;
            stack[top][0]=m-1;
            stack[top][1]=1;
            stack[top][3]=1; 
            continue;
            l1:
            stack[top][2]=stack[top+1][2];
        }
        else
        {
            top++;
            stack[top][0]=m-1;
            top++;
            stack[top][0]=m;
            stack[top][1]=n-1;
            stack[top][3]=2;
            continue;
            l2:
            stack[top][1]=stack[top+1][2];
            stack[top][3]=3;
            continue;
            l3:
            stack[top][2]=stack[top+1][2];
        }
        if (top==0)
            break;
        top--;
        switch (stack[top+1][3])
        {
            case 1:goto l1;
            case 2:goto l2;
            case 3:goto l3; 
        }
    }
    return stack[0][2];
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值