Ackermann函数(阿克曼函数)的递归、非递归(手动栈模拟)
目录
- 一、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时,函数求得了具体值,先更新返回值ret
为n + 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函数(阿克曼函数)的递归、非递归(手动栈模拟)相关推荐
- 快排递归非递归python_Python递归神经网络终极指南
快排递归非递归python Recurrent neural networks are deep learning models that are typically used to solve ti ...
- 二叉树的深度(前序 中序 后序 递归非递归搜素)、广度、搜索 C++
a b c 使用 1 2 3 表示 /* 描述:二叉树的深度(前序 中序 后序 递归非递归搜素).广度.搜索 作者:jz 日期:20140819 */ #include<stdio.h> ...
- 图的遍历(递归+非递归)
图遍历一共有四种,邻接矩阵的BFS与DFS,邻接表的BFS与DFS 还有BFS(BFS没有递归!)与DFS递归与非递归: 目录 DFS 手工 邻接矩阵 递归 非递归 邻接表 递归 非递归 BFS 手工 ...
- 一文彻底搞定二叉树的前序、中序、后序遍历(图解递归非递归)
前言 大家好,我是bigsai,在数据结构与算法中,二叉树无论是考研.笔试都是非常高频的考点内容,在二叉树中,二叉树的遍历又是非常重要的知识点,今天给大家讲讲二叉树的层序遍历. 这部分很多人可能会但是 ...
- java 建树源码_Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】...
import java.util.ArrayDeque; import java.util.Queue; import java.util.Stack; //二叉树的建树,前中后 递归非递归遍历 层序 ...
- c语言折半查找递归程序,C语言数据结构中二分查找递归非递归实现并分析
C语言数据结构中二分查找递归非递归实现并分析 前言: 二分查找在有序数列的查找过程中算法复杂度低,并且效率很高.因此较为受我们追捧.其实二分查找算法,是一个很经典的算法.但是呢,又容易写错.因为总是考 ...
- 二叉树——中序遍历(递归/非递归)
中序遍历,即遍历顺序为:左节点.根节点.右节点. 二叉树节点: public class Node {public Node left;public Node right;public int val ...
- 树的深度 递归非递归实现
树的深度 递归非递归实现 package com.dugstudio.SwordToOffer;import java.util.LinkedList;/*** 树的深度递归和非递归算法*/ clas ...
- Java 二叉树后序遍历(递归/非递归)
Java 二叉树后序遍历(递归/非递归) 简介: 遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次. 设L.D.R分 ...
- java建树_Java实现的二叉树常用操作【前序建树,前中后递归非递归遍历及层序遍历】...
本文实例讲述了Java实现的二叉树常用操作.分享给大家供大家参考,具体如下: import java.util.ArrayDeque; import java.util.Queue; import j ...
最新文章
- 果粉们注意了 外媒爆料以下机型不再支持iOS 13
- python列表导出csv_将Python列表导出到csv
- java web权限设计_java web简单权限管理设计
- ajax 用户验证js,js ajax验证用户名
- 内联函数inline,无比节省开销的
- python客户端与服务器端通信_python客户端与服务器端的通信
- 启用windows功能NetFx3时出错
- AI:人工智能领域之AI发展历史的重要历史时间节点、大牛们对AI相关概念的定义
- 基于视觉无人机的高速公路违章识别技术
- python 弧度制和角度制相互转换(math库和numpy库);计算反正余弦正切值
- 水哥王昱珩直播解锁华为Mate 20黑科技,超微距效果实力非凡
- 为什么要用大写L替换小写L(l),idea提醒literal ‘xxx‘ ends with lowercase ‘l‘
- Codeforces965—A:Paper Airplanes(思维)
- js实现Base64的加密解密
- 清华大学《大数据实践课》总结交流会成功举行
- 夏季养生知识为居民提供健康指导
- 手机铃声和图片的详细设计说明
- visual basic 6 下载 和 Vb6sp6 下载
- 树莓派入门(一) - 下载安装系统镜像,Raspbian和Centos
- win10如何让窗口固定保持在最上层