我正在尝试解决一个需要递归回溯的问题,而我的解决方案会产生堆栈溢出错误。我知道这个错误通常表示终止条件不好,但我的终止条件似乎是正确的。除了可能导致堆栈溢出错误的错误终止条件之外还有什么吗?我怎样才能弄清问题是什么?
编辑:抱歉试图发布代码,但它太丑了..
答案 0 :(得分:5)
正如@irreputable所说,即使您的代码具有正确的终止条件,也可能是问题对于堆栈来说太大了(因此在达到条件之前堆栈已经耗尽)。还有第三种可能性:你的递归已进入循环。例如,在深度优先搜索图表时,如果您忘记将节点标记为已访问,则最终会进入圈子,重新访问您已经看过的节点。
如何确定您所处的这三种情况中的哪一种?尝试描述每个递归调用的“位置”(这通常涉及函数参数)。例如,如果您正在编写图算法,其中函数在相邻节点上调用自身,则节点名称或节点索引可以很好地描述递归函数的位置。在递归函数的顶部,您可以打印描述,然后您将看到该函数的作用,也许您可以判断它是否做正确的事情,或者它是否在圈内。您还可以将描述存储在HashMap中,以便检测您是否输入了一个圆圈。
答案 1 :(得分:3)
不是使用递归,而是总是有一个使用堆栈的循环。例如。而不是(伪代码):
function sum(n){
if n == 0, return 0
return n + sum(n-1)
}
使用:
function sum(n){
Stack stack
while(n > 0){
stack.push(n)
n--
}
localSum = 0
while(stack not empty){
localSum += stack.pop()
}
return localSum
}
简而言之,通过将状态保存在本地堆栈中来模拟递归。
答案 2 :(得分:1)
如果您的问题太大而无法修复默认的堆栈限制大小,您可以使用-Xss选项为堆栈提供更多内存。
答案 3 :(得分:1)
正如其他人已经提到的那样,可能没有多少理由:
您的内存太小,无法将递归调用的次数保持在堆栈中。 Big Fibonacci数字可能就是一个很好的例子。只是FYI Fibonacci如下(有时从零开始):
1,1,2,3,5,8,13,...
Fn = Fn-1 + Fn-2
F0 = 1,F1 = 1,n> = 2
答案 4 :(得分:0)
如果你的代码是正确的,那么堆栈对你的问题来说太小了。我们没有真正的图灵机。
答案 5 :(得分:0)
有两个常见编码错误可能导致程序进入无限循环(因此导致堆栈溢出):
示例:
public static int factorial( int n ){
if( n < n ) // Bad termination condition
return 1;
else
return n*factorial(n+1); // Bad recursion call
}
否则,您的程序可能正常运行且堆栈太小。