堆栈溢出错误java

时间:2011-06-07 22:28:48

标签: java recursion stack-overflow backtracking

我正在尝试解决一个需要递归回溯的问题,而我的解决方案会产生堆栈溢出错误。我知道这个错误通常表示终止条件不好,但我的终止条件似乎是正确的。除了可能导致堆栈溢出错误的错误终止条件之外还有什么吗?我怎样才能弄清问题是什么?

编辑:抱歉试图发布代码,但它太丑了..

6 个答案:

答案 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
}

否则,您的程序可能正常运行且堆栈太小。