Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我仍然使用尾部递归斐波那契算法烧坏堆栈?_Java_Stack Overflow_Dynamic Programming_Tail Recursion_Memoization - Fatal编程技术网

Java 为什么我仍然使用尾部递归斐波那契算法烧坏堆栈?

Java 为什么我仍然使用尾部递归斐波那契算法烧坏堆栈?,java,stack-overflow,dynamic-programming,tail-recursion,memoization,Java,Stack Overflow,Dynamic Programming,Tail Recursion,Memoization,n=1000之前的堆栈溢出。是因为对long[]参数的引用,JVM觉得需要保留每个堆栈帧(胡乱猜测),还是我做了其他错误的事情 public static void main(String[] args) { long start = System.currentTimeMillis(); fibonacciMemoized(1000); long end = System.currentTimeMillis(); Syst

n=1000之前的堆栈溢出。是因为对long[]参数的引用,JVM觉得需要保留每个堆栈帧(胡乱猜测),还是我做了其他错误的事情

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        fibonacciMemoized(1000);
        long end = System.currentTimeMillis();
        System.out.println("\nTotal run time: " + (end-start));
    }

    public static void fibonacciMemoized(int n) {
        long[] fibMemos = new long[n+1];
        for (int i = 0;  i < fibMemos.length; i++) {
            fibMemos[i] = Long.MAX_VALUE;
        }
        long fibResult = fib(n, 1, 0, fibMemos);
        System.out.println(fibResult);
    }

    public static long fib(int n, long fibAcc, long fibPrev, long[] fibMemos) {
        if (fibMemos[n] != Long.MAX_VALUE){
            return fibMemos[n];
        } else if (n == 0) {
            return fibPrev;
        } else if (n == 1){
            return fibAcc;
        } else {
            long result = fib(n-1, fibAcc+fibPrev, fibAcc, fibMemos);
            fibMemos[n] = result;
            return result;
        }
    }
publicstaticvoidmain(字符串[]args){
长启动=System.currentTimeMillis();
斐波那契化(1000);
long end=System.currentTimeMillis();
System.out.println(“\n总运行时间:”+(结束-开始));
}
公共静态无效光纤接入(int n){
long[]fibmomes=新的long[n+1];
对于(int i=0;i
我想这与其说是评论,不如说是回答:

为什么我仍然使用尾部递归斐波那契算法烧坏堆栈


因为Java不支持尾部调用消除。

尝试使用选项来增加堆栈,比如Java-Xss4m或更多


注意:使用-Xss设置每个线程的堆栈大小,这是一个非常糟糕的主意。

记忆化的关键问题是,记忆化函数的后续调用将对相同的参数使用预先计算的值


在您的代码中,您以前没有调用过该函数,因此之前没有可重复使用的结果,您开始使用值1000调用它,这将在
fib()的末尾使用
fib(n-1,fibAcc+fibprov,fibAcc,fibmomes)进行递归调用。
,所以你用1000个递归调用来破坏堆栈。

它支持它,你只需要给自己写,呵呵。@Thomas:是的,我想任何带有循环的语言都“支持”消除尾部调用:)这解释了很多,哈哈。@Thomasmclod-这就像说汇编语言支持函数式编程一样。这不是人们通常所说的“支持”的意思。在这种情况下,正确的答案也是“因为您实际上没有实现递归函数”。我的意思是,是的,它在任何情况下都不会有帮助,但是
foo(X):foo(X);bar=Y
be tail recursive?如何以自上而下的方式将值输入到FIBMomes中?好的,我想我明白了,这种记忆化方案只有在您仍在进行两个递归调用时才有效,比如'fib(n-2)+fib(n-1)。。。。。