16

我正在编写一个可以调用自身多达 5000 次的函数。当然,我得到一个StackOverflowError. 有什么方法可以以相当简单的方式重写此代码?:

void checkBlocks(Block b, int amm) {

    //Stuff that might issue a return call

    Block blockDown = (Block) b.getRelative(BlockFace.DOWN);
    if (condition) 
        checkBlocks(blockDown, amm);


    Block blockUp = (Block) b.getRelative(BlockFace.UP);
    if (condition) 
        checkBlocks(blockUp, amm);

    //Same code 4 more times for each side

}

顺便问一下,我们可以调用函数的深度有什么限制?

4

6 回答 6

20

使用明确的对象堆栈和循环,而不是调用堆栈和递归:

void checkBlocks(Block b, int amm) {
  Stack<Block> blocks = new Stack<Block>();
  blocks.push(b);
  while (!blocks.isEmpty()) {
    b = blocks.pop();
    Block blockDown = (Block) b.getRelative(BlockFace.DOWN);
    if (condition)
      blocks.push(block);
    Block blockUp = (Block) b.getRelative(BlockFace.UP);
    if (condition) 
      blocks.push(block);
  }
}
于 2012-04-09T12:57:07.000 回答
7

java中的默认堆栈大小为512kb。如果超过该程序将终止抛出 StackOverflowException

您可以通过传递 JVM 参数来增加堆栈大小:-Xss1024k

现在堆栈大小为 1024kb。您可以根据您的环境给予更高的价值

我认为我们不能以编程方式改变这一点

于 2012-04-09T13:05:15.827 回答
0

您可以使用 -Xss4m 增加堆栈大小。

于 2012-04-09T12:57:49.447 回答
0

只要块可用,您就可以将“块”放入队列/堆栈中并进行迭代。

于 2012-04-09T12:58:34.550 回答
0

很明显,您获得了具有递归分支因子的 StackOverflow。在其他语言中,它可以通过 Tail Call Optimization来实现。但我想你的问题需要另一种方法来解决。

理想情况下,您对 Block 进行一些检查。也许您可以获取所有块的列表并迭代检查每个块?

于 2012-04-09T13:00:28.837 回答
0

在大多数情况下,递归的使用方式是错误的。您不应该得到堆栈溢出异常。您的方法没有返回类型/值。你如何确保你的初始块 b 是有效的?

如果您使用递归,请回答以下问题:

  • 我的递归锚是什么(我什么时候停止递归)
  • 我的递归步骤是什么(如何减少计算次数)

例子:

  • 嗯!=> n*n-1!

我的递归锚是 n == 2(结果是 2),所以我可以计算从这个锚开始的所有结果。

我的递归步骤是 n-1 (所以每一步我都更接近解决方案(实际上是我的递归锚点))

于 2012-04-09T14:45:42.730 回答