如何避免递归函数的StackOverflowError
我正在编写一个函数,可以调用自己大约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 }
顺便说一下,我们可以称之为function的深度有多大?
使用显式堆栈对象和循环,而不是调用堆栈和递归:
void checkBlocks(Block b, int amm) { Stack blocks = new Stack (); 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); } }
java中的默认堆栈大小为512kb。 如果超过该程序将终止抛出StackOverflowException
您可以通过传递JVM参数来增加堆栈大小:-Xss1024k
现在堆栈大小是1024kb。 您可以根据您的环境提供更高的价值
我认为我们不能以编程方式改变这一点
您可以使用-Xss4m增加堆栈大小。
您可以将“块”放入队列/堆栈中,只要块可用就进行迭代。
很明显,你的StackOverflow具有递归的分支因子。 在其他语言中,它可以通过Tail Call Optimization实现。 但我想你的问题需要另一种方法来解决。
理想情况下,您对Block执行一些检查。 也许你可以获得所有块的列表并迭代地检查它们中的每一个?
在大多数情况下,递归以错误的方式使用。 您不应该获得堆栈溢出exception。 您的方法没有返回类型/值。 您如何确保您的初始Block b有效?
如果您正在使用递归,请回答以下问题:
- 什么是我的递归锚(什么时候我停止递归)
- 什么是我的递归步骤(如何减少我的计算次数)
例:
- N! => n * n-1!
我的递归锚点是n == 2(结果是2),所以我可以计算从这个锚点开始的所有结果。
我的递归步骤是n-1(所以每一步我都接近解决方案(在这个事实中我的递归锚))