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;
}
}
分享到:
相关推荐
在这个主题中,我们将深入探讨如何用非递归算法来实现大数阶乘计算,并且利用ArrayList来存储中间结果。 首先,让我们了解阶乘的概念。阶乘是数学中的一个运算,对于非负整数n,其阶乘表示为所有小于等于n的正整数...
本文将详细介绍一个用Java编写的递归算法实例,该实例用于实现字符数组的所有可能全排列。通过这个例子,我们可以深入理解递归的基本概念、工作原理以及如何在实际编程中应用递归来解决问题。 #### 代码解析 #####...
本篇将重点讲解如何利用ArrayList实现快速排序(Quick Sort)、归并排序(Merge Sort)和堆排序(Heap Sort)这三种经典的排序算法,并探讨它们的原理、优缺点以及在实际应用中的选择。 **快速排序(Quick Sort)**...
在Java编程语言中,ArrayList是Java集合框架的重要组成部分,它属于List接口的一个具体实现,用于存储可变大小的有序对象列表。在这个“ArrayList实现对产品CRUD”的项目中,我们将探讨如何利用面向对象编程(OOP)...
浅析ArrayList内部实现 ArrayList是Java集合框架中的一种常用数据结构,能够存储任意多个对象,并且可以自由扩展,弥补了数组的定长的缺陷。下面我们将深入探讨ArrayList的内部实现机理。 ArrayList的内部实现机理...
ArrayList是Java集合框架中常用的动态数组,它是List接口的一个实现,允许存储包括null在内的所有元素。ArrayList的主要特点是通过数组来存储元素,提供了丰富的操作方法,包括添加、删除、修改和查询等。下面是...
在这个场景中,我们将探讨如何利用ArrayList来实现ListView,以及如何添加编辑、新增、删除功能,以及在Activity间传递参数,同时还会涉及到ContextMenu和OptionsMenu的实现,以及长按事件的处理。 首先,我们需要...
模拟ArrayList底层实现 在Java中,ArrayList是一种常用的集合类,提供了许多实用的方法来操作集合数据,而本文则尝试模拟ArrayList的底层实现,通过自定义集合实现类MyArrayList,来实现基本的集合操作。 模拟...
### Java使用递归算法求交错幂集(源代码) ...通过递归算法,我们成功实现了交错幂集的概念,并通过Java语言进行了具体实现。这种方法不仅能够清晰地展示递归的思想,而且也适用于解决实际问题中类似的组合问题。
用java自己实现的arrayList,比较详细,有助于初学者理解arrayList的基本概念和基础用法
实现一个学生成绩管理的简单系统。要求可以添加、删除、修改、查询成绩 创建界面相关的接口:将菜单中显示的内容定义成若干字符串常量,放入一个接口Menu中以便使用 TestDemo(主类) import java.util.ArrayList; ...
使用Java的集合框架,如ArrayList和HashMap,可以方便地实现这些数据结构和操作。 在提供的`fpgrowth`文件中,可能包含了FP树算法的具体Java实现代码,包括类定义、方法实现以及可能的数据示例。通过阅读和理解这段...
但是,迭代过程中修改ArrayList(非迭代器自身调用的remove方法)可能不会抛出异常,而是造成未定义的行为,因此在并发编程中需要格外注意。 了解ArrayList的内部机制对于优化代码性能至关重要。例如,预估...
Java集合框架中,ArrayList是一种常见的集合实现类,用于存储和操作对象集合。ArrayList基于动态数组的数据结构,因此它能够提供自动扩容的功能,同时也能够快速地进行随机访问。本篇文档将深入探讨ArrayList的内部...
此方法是通过java提供的ArrayList方法对栈的实现;
不过,根据标题和描述,这里我们讨论的是一个用C++实现的ArrayList类模板,它采用了双层散列技术来提高性能。这个实现旨在提供高效的数据存储和操作,特别是在处理大量数据时。 首先,让我们深入了解ArrayList的...
在Java编程中,ArrayList是一个常用的集合类,它继承自AbstractList并实现了List接口。ArrayList以动态数组的形式存储数据,提供了一种高效的方式来管理和操作对象序列。在这个场景中,我们使用ArrayList来实现用户...
**非递归算法实现** 方法二采用了非递归策略,使用ArrayList存储序列中的数字。首先,构造函数`Class1(int num)`初始化ArrayList并填充前`num`个斐波那契数。`Calculation`方法用于根据已存储的数字计算新的...