ArrayList实现Ackerman非递归算法

本文介绍如何通过栈模拟递归过程,实现Ackerman函数的非递归版本。使用ArrayList作为栈,详细阐述了算法思路及Java实现代码。

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

Ackerman(m,n)函数的递归定义为
public static int ackerman(int a,int b){
if(a==0)
return b+1;
else if(a!=0&&b==0)
return ackerman(a-1,1);
else
return ackerman(a-1,ackerman(a,b-1));
}

递归转换为非递归需要使用栈来模拟递归
那么就选用ArrayList充当下栈吧,对我来说用起来比较熟悉,你可以使用java自己的Stack类

栈结构为
m n result

把它写成一个bean作为我们的栈的一个小块
class Stack{
private int m;
private int n;
private int result;

public Stack(int m,int n,int result){
this.m=m;
this.n=n;
this.result=result;
}
get/set()方法省略
}


n或result=-1时代表解暂时未得到

下面是实现算法的主要思想
while(栈非空&&没有得到答案){
取栈顶对象stacktemp
if(该元素.result还没有解){
if(m和n都!=0){
//因为Ackerman在这个情况下会分解成2个函数,所以都要进栈
new stack1(m-1,-1,-1)进栈
new stack2(m,n-1,-1)进栈
ArrayList.add(stack1和stack2);
}
else if(n==0){
//这个情况下只分解为一个函数
new stack(m-1,1,-1)进栈
}
else if(m==0){
//这个情况可以得到stacktemp的结果,即n+1;
修改stacktemp的result
}
}
//如果的到的stacktemp是有解的进行出栈动作
else{
if(栈的长度==1){
//说明得到我们的结果了
得到结果
设置一个flag让循环可以终止
}
if(stacktemp.m为0){
将stacktemp.result传给上一个栈的result
stacktemp出栈
}
else if(stacktemp.m!=0){
if(如果上一个栈的n==-1){
该元素的结果传给上一个栈的n
stacktemp出栈
}
else{
//这是关键点,因为Ackerman函数是双递归,需要递归2次,这个else恰好是2个分支的交汇处
将stacktemp.result传给上一个栈的result
stacktemp出栈
}
}
}
}

完整代码如下
package com.datastructure;

import java.util.ArrayList;
import java.util.Calendar;

public class AckermanWithoutCycle {

/**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成方法存根
int result=-1;
boolean gotAnswer=false;
long starttime=-1;
long endtime=-1;
// System.out.println("请输入Ackerman的2个参数");
// Scanner sc=new Scanner(System.in);
// int a=sc.nextInt();
// int b=sc.nextInt();
int a=4;
int b=1;
ArrayList<Stack> stacklist=new ArrayList<Stack>();
Stack stack=new Stack(a,b,-1);
stacklist.add(stack);
starttime=Calendar.getInstance().getTimeInMillis();
while(stacklist.size()>0&&!gotAnswer){
//取栈顶元素
Stack stacktemp=stacklist.get(stacklist.size()-1);
//如果该元素还没有解
if(stacktemp.getResult()==-1){
if(stacktemp.getM()!=0&&stacktemp.getN()!=0){
Stack stack1=new Stack(stacktemp.getM()-1,-1,-1);
Stack stack2=new Stack(stacktemp.getM(),stacktemp.getN()-1,-1);
stacklist.add(stack1);
stacklist.add(stack2);
}
else if(stacktemp.getN()==0){
Stack stack1=new Stack(stacktemp.getM()-1,1,-1);
stacklist.add(stack1);
}
//如果m==0那么该栈的解是n+1
else if(stacktemp.getM()==0&&stacktemp.getN()!=-1){
stacktemp.setResult(stacktemp.getN()+1);
}
}
//如果该元素有解
else{
if(stacklist.size()==1){
result=stacktemp.getResult();
gotAnswer=true;
endtime=Calendar.getInstance().getTimeInMillis();
break;
}
//如果m为0
if(stacktemp.getM()==0){
//讲该元素的结果传给上一个栈的result
stacklist.get(stacklist.size()-2).setResult(stacktemp.getResult());
stacklist.remove(stacktemp);
}
//如果不为0
else if(stacktemp.getM()!=0){
//如果上一个栈的n==-1,该元素的结果传给上一个栈的n
if(stacklist.get(stacklist.size()-2).getN()==-1){
stacklist.get(stacklist.size()-2).setN(stacktemp.getResult());
stacklist.remove(stacktemp);
}
else{
stacklist.get(stacklist.size()-2).setResult(stacktemp.getResult());
stacklist.remove(stacktemp);
}
}
}
}
System.out.println("结果为:"+result+"耗时"+(endtime-starttime)+"ms");
}
}
class Stack{
private int m;
private int n;
private int result;

public Stack(int m,int n,int result){
this.m=m;
this.n=n;
this.result=result;
}
public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值