Java 如何以非递归方式重写Ackermann函数?

Java 如何以非递归方式重写Ackermann函数?,java,non-recursive,Java,Non Recursive,我有功能 public static int func(int M,int N){ if(M == 0 || N == 0) return M+N+1; return func(M-1, func(M, N-1)); } 如何以非递归方式重写它? 也许,它实现了一些算法吗?这看起来像是家庭作业,所以我不会给你答案,但我会指引你正确的方向: 如果您想分解递归,在递归过程中列出所有值可能会很有用,让m={0…x}n={0…y} 例如: m = 0, n = 0 = f(0,0) =

我有功能

public static int func(int M,int N){
    if(M == 0 || N == 0) return M+N+1;
    return func(M-1, func(M, N-1));
}
如何以非递归方式重写它?
也许,它实现了一些算法吗?

这看起来像是家庭作业,所以我不会给你答案,但我会指引你正确的方向:

如果您想分解递归,在递归过程中列出所有值可能会很有用,让m={0…x}n={0…y}

例如:

m = 0, n = 0 = f(0,0) = M+N+1 = 1
m = 1, n = 0 = f(1,0) = M+N+1 = 2
m = 1, n = 1 = f(1,1) = f(0,f(1,0)) = f(0,2) = 3
m = 2, n = 1 = f(2,1) = f(1,f(2,0)) = f(1,3) = f(0,f(1,2)) = f(0,f(0,f(1,1))
             = f(0,f(0,3))          = f(0,4) = 5
有了它,您可以得到一个可以使用的非递归关系(非递归函数定义)

编辑:看起来这是一个总的可计算函数,它不是原始递归的。

不完全是O(1),但绝对是非递归的

public static int itFunc(int m, int n){
    Stack<Integer> s = new Stack<Integer>;
    s.add(m);
    while(!s.isEmpty()){
        m=s.pop();
        if(m==0||n==0)
            n+=m+1;
        else{
            s.add(--m);
            s.add(++m);
            n--;
        }
    }
    return n;
}
public static int itFunc(int m,int n){
堆栈s=新堆栈;
s、 加(m);
而(!s.isEmpty()){
m=s.pop();
如果(m==0 | | n==0)
n+=m+1;
否则{
s、 加(--m);
s、 加(++m);
n--;
}
}
返回n;
}

这是我自己已经检查过的正确版本

public static int Ackermann(int m, int n){
Stack<Integer> s = new Stack<Integer>;
s.add(m);
while(!s.isEmpty()){
    m=s.pop();
    if(m==0) { n+=m+1; }
    else if(n==0)
    {
       n += 1;
       s.add(--m);
    }
    else{
        s.add(--m);
        s.add(++m);
        n--;
    }
}
return n;
}
publicstaticintackermann(intm,intn){
堆栈s=新堆栈;
s、 加(m);
而(!s.isEmpty()){
m=s.pop();
如果(m==0){n+=m+1;}
else如果(n==0)
{
n+=1;
s、 加(--m);
}
否则{
s、 加(--m);
s、 加(++m);
n--;
}
}
返回n;
}

我无法得到@LightyearBuzz的答案,但我从中找到了对我有用的Java 5代码:

import java.util.HashMap;
import java.util.Stack;

public class Ackerman {
  static class  Pair <T1,T2>{
    T1 x; T2 y;
    Pair(T1 x_,T2 y_) {x=x_; y=y_;}
    public int hashCode() {return x.hashCode() ^ y.hashCode();}
    public boolean equals(Object o_) {Pair o= (Pair) o_; return x.equals(o.x) && y.equals(o.y);}
  }

  /**
   * @param args
   */
  public static int ack_iter(int m, int n) {
    HashMap<Pair<Integer,Integer>,Integer> solved_set= new HashMap<Pair<Integer,Integer>,Integer>(120000);
    Stack<Pair<Integer,Integer>> to_solve= new Stack<Pair<Integer,Integer>>();
    to_solve.push(new Pair<Integer,Integer>(m,n));

    while (!to_solve.isEmpty()) {
      Pair<Integer,Integer> head= to_solve.peek();
      if (head.x.equals(0) ) {
        solved_set.put(head,head.y + 1);
        to_solve.pop();
      }
      else if (head.y.equals(0)) {
        Pair<Integer,Integer> next= new Pair<Integer,Integer> (head.x-1,1);
        Integer result= solved_set.get(next);
        if(result==null){
          to_solve.push(next);
        } 
        else {
          solved_set.put(head, result);
          to_solve.pop();
        }
      }
      else {
        Pair<Integer,Integer> next0= new Pair<Integer,Integer>(head.x, head.y-1);
        Integer result0= solved_set.get(next0);
        if(result0 == null) {
          to_solve.push(next0);
        }
        else {
          Pair<Integer,Integer> next= new Pair<Integer,Integer>(head.x-1,result0);
          Integer result= solved_set.get(next);
          if (result == null) {
            to_solve.push(next);
          }
          else {
            solved_set.put(head,result);
            to_solve.pop();
          }
        }
      }
    }
    System.out.println("hash size: "+solved_set.size());
    System.out.println("consumed heap: "+ (Runtime.getRuntime().totalMemory()/(1024*1024)) + "m");
    return solved_set.get(new Pair<Integer,Integer>(m,n));
  }
}
import java.util.HashMap;
导入java.util.Stack;
公共级阿克曼{
静态类对{
T1×t2y;
对(T1 x_u2;,t2y_2;){x=x;y=y_2;}
public int hashCode(){返回x.hashCode()^y.hashCode();}
公共布尔等于(对象o){Pair o=(Pair)o;返回x.equals(o.x)&&y.equals(o.y)}
}
/**
*@param args
*/
公共静态int ack_iter(int m,int n){
HashMap solved_set=新的HashMap(120000);
堆栈到_solve=新堆栈();
求解推(新对(m,n));
而(!to_solve.isEmpty()){
Pair head=to_solve.peek();
如果(头x等于(0)){
已解决的_集放置(头部,头部y+1);
要解决。pop();
}
else if(头y等于(0)){
下一对=新对(头部x-1,1);
整数结果=已求解的集合.get(下一步);
如果(结果==null){
要解决问题,请按(下一步);
} 
否则{
已解决的集合放置(头、结果);
要解决。pop();
}
}
否则{
配对next0=新配对(头部x,头部y-1);
整数result0=已求解的集合.get(next0);
如果(结果0==null){
求解.推送(next0);
}
否则{
下一对=新对(头部x-1,结果0);
整数结果=已求解的集合.get(下一步);
如果(结果==null){
要解决问题,请按(下一步);
}
否则{
已解决的集合放置(头、结果);
要解决。pop();
}
}
}
}
System.out.println(“哈希大小:+solved_set.size());
System.out.println(“消耗的堆:+(Runtime.getRuntime().totalMemory()/(1024*1024))+“m”);
返回已求解的_集get(新对(m,n));
}
}

之前发布的所有答案都没有正确实现Ackermann

def acker_mstack(m, n)
  stack = [m]
  until stack.empty?
    m = stack.pop

    if m.zero?
      n += 1
    elsif n.zero?
      stack << m - 1
      n = 1
    else
      stack << m - 1 << m
      n -= 1
    end
  end
  n
end
def acker\u mstack(m,n)
堆栈=[m]
直到堆栈。空?
m=stack.pop
如果m.zero?
n+=1
埃尔西夫零号?

堆栈用python编写,仅使用1个数组和1个变量,希望这有帮助

def acker(m,n):

    right = [m]
    result = n
    i = 0

    while True:
        if len(right) == 0:
            break

        if right[i] > 0 and result > 0:
            right.append(right[i])
            right[i] -= 1
            result -= 1
            i += 1

        elif right[i] > 0 and result == 0:
            right[i] -= 1
            result = 1

        elif right[i] == 0:
            result += 1
            right.pop()
            i -=1

    return result

而(M!=0 | | N!=0){\\todo}
闻起来像是作业。您尝试过什么?这应该会给您一些想法:由于嵌套的
func
调用,这是一种从琐碎到不递归的方法。祝你好运:)在我看来,或者这个函数类似于?@KDiTraglia你是对的-我甚至在第三个方程上都得到了正确的结果。谢谢:)m=2,n=1,我得到4。n=1,s={2}->n=1,m=2->n=0,s={3,1}->n=0,m=3->n=3+1=4。除非我的答案f(2,1)上的数学是错的?是的,你的数学是错的。我对照他提供的密码检查了一下我哪里出错了?我一定看到了脱节,因为复习数学给了我一个正确的答案我已经把我的答案通读了一遍,我没有错。这个答案并不正确。编辑:我下面的代码是错误的,我道歉。我以为你的意思是我的答案中的数学是错误的。@Lightyear Buzz这个实现似乎从m=3,n=0开始就出错了。(Wolfram Alpha的回答是5,此代码返回4)我非常感谢更新,我对上面的代码理解不够,无法自己完成-感谢任何帮助!这似乎是@LightyearBuzz答案的一个很小的变化,在这里,您使用
n==0
案例的堆栈一次执行一个增量,而不是光年的
n+=m+1,从而进行了去优化。你真的是自己写的吗?或者这大部分是从另一个答案中抄袭过来的(没有学分)?这个答案只是对LightyearBuzz的答案做了一个小小的改变,我很抱歉在没有通知他的情况下使用了他的代码。因为我看到他的代码不能通过所有的例子,所以我做了一些修改来纠正它。如果你不喜欢它,我可以删除它。但是我只是想让人们看到正确的答案^^你应该做的是回答它修复了什么bug。(即哪个输入给出了错误的答案)。e、 g.“LightyearBuzz的答案对于
A(废话,废话)
是错误的。我通过更改废话来修复它。下面是完整的代码:“这解决了接受答案的问题。作为参考,
A(4,1)
计算大约需要60秒。谢谢!你能解释一下你是如何做到这一点的吗?我不确定如何将其推广到具有不同算术的函数,例如阶乘只接受一个参数。如何将其转换为具有自定义堆栈的循环版本?首先,了解递归。第二,重用递归函数体,重构为只有一个入口点和出口点。第三,通过按下和弹出inpu手动实现调用堆栈