Java 堆栈溢出错误
我正试图解决一个需要递归回溯的问题,而我的解决方案会产生堆栈溢出错误。我知道此错误通常表示终止条件不好,但我的终止条件似乎是正确的。除了糟糕的终止条件外,是否还有其他可能导致stackoverflow错误的因素?我怎样才能找出问题所在Java 堆栈溢出错误,java,recursion,stack-overflow,backtracking,Java,Recursion,Stack Overflow,Backtracking,我正试图解决一个需要递归回溯的问题,而我的解决方案会产生堆栈溢出错误。我知道此错误通常表示终止条件不好,但我的终止条件似乎是正确的。除了糟糕的终止条件外,是否还有其他可能导致stackoverflow错误的因素?我怎样才能找出问题所在 编辑:抱歉,试图发布代码,但太难看了。如果代码正确,那么堆栈对于您的问题来说太小了。我们没有真正的图灵机器 正如@unreputable所说,即使您的代码具有正确的终止条件,也可能是因为问题对于堆栈来说太大了(因此在达到条件之前堆栈已耗尽)。还有第三种可能性:递归
编辑:抱歉,试图发布代码,但太难看了。如果代码正确,那么堆栈对于您的问题来说太小了。我们没有真正的图灵机器 正如@unreputable所说,即使您的代码具有正确的终止条件,也可能是因为问题对于堆栈来说太大了(因此在达到条件之前堆栈已耗尽)。还有第三种可能性:递归已进入循环。例如,在通过图形进行深度优先搜索时,如果您忘记将节点标记为已访问,则最终将进入圆圈,重新访问您已经看到的节点
您如何确定您处于这三种情况中的哪一种?设法描述每个递归调用的“位置”(这通常涉及函数参数)。例如,如果您正在编写一个图算法,其中函数在相邻节点上调用自身,那么节点名或节点索引是递归函数所在位置的良好描述。在递归函数的顶部,您可以打印描述,然后您将看到函数的功能,也许您可以判断它是否做了正确的事情,或者它是否在循环中。您还可以将描述存储在HashMap中,以检测是否已输入圆。如果问题太大而无法在默认堆栈限制大小内修复,则可以使用-Xss选项为堆栈提供更多内存。您可以使用堆栈的循环,而不是使用递归。例如,代替(伪代码): 使用:
简而言之,通过将状态保存在本地堆栈中来模拟递归。有两个常见的编码错误可能会导致程序进入无限循环(从而导致堆栈溢出):
- 不良终止条件
- 错误的递归调用
public static int factorial( int n ){
if( n < n ) // Bad termination condition
return 1;
else
return n*factorial(n+1); // Bad recursion call
}
公共静态整数阶乘(int n){
if(n
否则,您的程序可能运行正常,堆栈太小。正如其他人已经提到的,可能有一些原因:
- 您的代码在本质上或递归逻辑上存在问题。它必须是任何递归函数的停止条件、基本情况或终止点
- 内存太小,无法将递归调用的数量保留在堆栈中。大斐波那契数可能是一个很好的例子。仅供参考,斐波那契如下(有时从零开始): 1,1,2,3,5,8,13 Fn=Fn-1+Fn-2 F0=1,F1=1,n>=2
function sum(n){
Stack stack
while(n > 0){
stack.push(n)
n--
}
localSum = 0
while(stack not empty){
localSum += stack.pop()
}
return localSum
}
public static int factorial( int n ){
if( n < n ) // Bad termination condition
return 1;
else
return n*factorial(n+1); // Bad recursion call
}