目录

  • 一、Ackermann函数
  • 二、C++实现
    • 1. 递归实现
    • 2. 栈模拟递归

一、Ackermann函数

Ack(m,n)={n+1m=0Ack(m−1,1)m>0,n=0Ack(m−1,Ack(m,n−1))m>0,n>0Ack(m,n)= \begin{cases} n+1& m=0\\ Ack(m-1,1)& m>0,n=0\\ Ack(m-1,Ack(m,n-1))& m>0,n>0 \end{cases}Ack(m,n)=⎩⎪⎨⎪⎧​n+1Ack(m−1,1)Ack(m−1,Ack(m,n−1))​m=0m>0,n=0m>0,n>0​
Ackermannn函数输出值增长速度非常快,仅是对于(4,3)的输出已大得不能准确计算。

Ack(0,n)=n+1Ack(1,n)=n+2Ack(2,n)=2n+3Ack(3,n)=2n+3−3Ack(4,n)=222⋅⋅⋅2−3(n+3个2)Ack(0,n)=n+1\\ Ack(1,n)=n+2\\ Ack(2,n)=2n+3\\ Ack(3,n)=2^{n+3}-3\\ Ack(4,n)=2^{2^{2^{\cdot^{\cdot^{\cdot^{2}}}}}}-3(n+3个2)Ack(0,n)=n+1Ack(1,n)=n+2Ack(2,n)=2n+3Ack(3,n)=2n+3−3Ack(4,n)=222⋅⋅⋅2−3(n+3个2)

二、C++实现

1. 递归实现

按照表达式直接写,非常简单。

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

2. 栈模拟递归

观察表达式,显然只有m=0m=0m=0的情况才能直接求得具体值,因此递归的出口一定m=0m=0m=0。

先将问题具体化,例如求Ack(2,1)Ack(2,1)Ack(2,1)的值,手动演算一下,每一次取栈顶的时候都同时出栈,栈的变化如图:

先分析不那么特殊的两种情况:
①n=0n=0n=0,如蓝框过程。
则(m−1,1)(m-1,1)(m−1,1)入栈。

②m>0,n>0m>0,n>0m>0,n>0,如红框过程。
由于nnn的值也需要通过AckAckAck函数求出,先标记为−1-1−1,即待求值,将(m−1,−1)(m-1,-1)(m−1,−1)入栈;
然后将求nnn的值的AckAckAck函数入栈,即(m,n−1)(m,n-1)(m,n−1)入栈。

然后考虑m=0m=0m=0的情况:
如绿框过程。由于m=0m=0m=0时,函数求得了具体值,先更新返回值retn + 1
通过栈是否为空判断是中间过程还是递归出口,栈空则说明达到了递归出口。
①中间过程,即前面一个绿框过程。
返回值为之前讨论的“用-1标记的待求的n”,因此更新栈顶的n
②递归出口,即后面的绿框过程。栈空,说明没有待更新、待求值的了,该返回值即最终结果。

#include <stack>int Ack_non_recursion(int m, int n) {struct Ack {    // Ackermann结构体int m_, n_;Ack(int m, int n) : m_(m), n_(n) {} // 构造函数} Node(m, n);stack<Ack> s;   // STL栈s.push(Node);   // 初始值入栈int ret = -1;   // Ackermann函数的返回值while(!s.empty()) {Node = s.top(); // 取栈顶的值s.pop();        // 并且出栈if(Node.m_ == 0) {  // 第一种情况,m 等于 0ret = Node.n_ + 1;  // 返回值为 n + 1if(s.empty())   // 如果栈空了,说明不需要继续向上返回,已经得到了最终结果break;      // 跳出循环Node = s.top(); // 否则,更新栈顶结点(第三种情况中 用 -1 标记的待计算的 n 的值)s.pop();        // 先出栈Node.n_ = ret;  // n 修改为返回值s.push(Node);   // 再重新入栈}else if(Node.n_ == 0) { // 第二种情况,n 等于 0s.push(Ack(Node.m_ - 1, 1));    // Ack(m - 1, 1) 入栈}else {  // 第三种情况,m, n 都大于 0s.push(Ack(Node.m_ - 1, -1));   // 用 -1 标记 n ,表示还没有计算出值,Ack(m - 1, -1) 入栈s.push(Ack(Node.m_, Node.n_ - 1));  // 要计算 n 的值,Ack(m, n - 1) 入栈}}return ret;
}

Ackermann函数(阿克曼函数)的递归、非递归(手动栈模拟)相关推荐

  1. 快排递归非递归python_Python递归神经网络终极指南

    快排递归非递归python Recurrent neural networks are deep learning models that are typically used to solve ti ...

  2. 二叉树的深度(前序 中序 后序 递归非递归搜素)、广度、搜索 C++

    a b c 使用 1 2 3 表示 /* 描述:二叉树的深度(前序 中序 后序 递归非递归搜素).广度.搜索 作者:jz 日期:20140819 */ #include<stdio.h> ...

  3. 图的遍历(递归+非递归)

    图遍历一共有四种,邻接矩阵的BFS与DFS,邻接表的BFS与DFS 还有BFS(BFS没有递归!)与DFS递归与非递归: 目录 DFS 手工 邻接矩阵 递归 非递归 邻接表 递归 非递归 BFS 手工 ...

  4. 一文彻底搞定二叉树的前序、中序、后序遍历(图解递归非递归)

    前言 大家好,我是bigsai,在数据结构与算法中,二叉树无论是考研.笔试都是非常高频的考点内容,在二叉树中,二叉树的遍历又是非常重要的知识点,今天给大家讲讲二叉树的层序遍历. 这部分很多人可能会但是 ...

  5. java 建树源码_Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】...

    import java.util.ArrayDeque; import java.util.Queue; import java.util.Stack; //二叉树的建树,前中后 递归非递归遍历 层序 ...

  6. c语言折半查找递归程序,C语言数据结构中二分查找递归非递归实现并分析

    C语言数据结构中二分查找递归非递归实现并分析 前言: 二分查找在有序数列的查找过程中算法复杂度低,并且效率很高.因此较为受我们追捧.其实二分查找算法,是一个很经典的算法.但是呢,又容易写错.因为总是考 ...

  7. 二叉树——中序遍历(递归/非递归)

    中序遍历,即遍历顺序为:左节点.根节点.右节点. 二叉树节点: public class Node {public Node left;public Node right;public int val ...

  8. 树的深度 递归非递归实现

    树的深度 递归非递归实现 package com.dugstudio.SwordToOffer;import java.util.LinkedList;/*** 树的深度递归和非递归算法*/ clas ...

  9. Java 二叉树后序遍历(递归/非递归)

    Java 二叉树后序遍历(递归/非递归) 简介: 遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次. 设L.D.R分 ...

  10. java建树_Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】...

    本文实例讲述了Java实现的二叉树常用操作.分享给大家供大家参考,具体如下: import java.util.ArrayDeque; import java.util.Queue; import j ...

最新文章

  1. 果粉们注意了 外媒爆料以下机型不再支持iOS 13
  2. python列表导出csv_将Python列表导出到csv
  3. java web权限设计_java web简单权限管理设计
  4. ajax 用户验证js,js ajax验证用户名
  5. 内联函数inline,无比节省开销的
  6. python客户端与服务器端通信_python客户端与服务器端的通信
  7. 启用windows功能NetFx3时出错
  8. AI:人工智能领域之AI发展历史的重要历史时间节点、大牛们对AI相关概念的定义
  9. 基于视觉无人机的高速公路违章识别技术
  10. python 弧度制和角度制相互转换(math库和numpy库);计算反正余弦正切值
  11. 水哥王昱珩直播解锁华为Mate 20黑科技,超微距效果实力非凡
  12. 为什么要用大写L替换小写L(l),idea提醒literal ‘xxx‘ ends with lowercase ‘l‘
  13. Codeforces965—A:Paper Airplanes(思维)
  14. js实现Base64的加密解密
  15. 清华大学《大数据实践课》总结交流会成功举行
  16. 夏季养生知识为居民提供健康指导
  17. 手机铃声和图片的详细设计说明
  18. visual basic 6 下载 和 Vb6sp6 下载
  19. 树莓派入门(一) - 下载安装系统镜像,Raspbian和Centos
  20. win10如何让窗口固定保持在最上层

热门文章

  1. 动态贝叶斯网络中TBN与DBN的区别
  2. Java 代码简单模拟商城购物车
  3. Android SDK HTTP Proxy Server
  4. 解决word插入图片移动以及遮挡问题
  5. 南京邮电大学计算机非全调剂,南京邮电大学2018年拟接收(非全日制)考研调剂公告...
  6. 计算机组成与设计答案
  7. 关于sql2008卸载后再安装问题
  8. Mixly 二次开发 自定义库 创客教程
  9. 给大家分享一下2018最新的Java黑马视频教程,包含十次方和乐优商城项目
  10. 艾斯是蒙奇·D·路飞的义兄