【问题标题】:Stack overflow on recursive function递归函数的堆栈溢出
【发布时间】:2017-10-20 19:28:32
【问题描述】:
遇到了递归函数的问题。我在java中做了这个,这是非常基本的,但由于堆栈溢出错误,它不起作用。我的意思是这个函数的作用是打开函数的频率与给定数字和您在主函数中声明的数字之间的差异大小一样,对于堆栈来说,这实际上不应该是问题,但是,好吧不能一直工作,或者这里的错误是什么......?
提前感谢您的回答:)
public class Übung_Baeume {
static int anzAufrufe=0;
static int zahl=23;
public static int zaehleAufrufe(int uebergabe)
{
anzAufrufe++;
if (uebergabe==zahl){
return anzAufrufe;
}
return zaehleAufrufe(uebergabe-1) +
zaehleAufrufe(uebergabe+1);
}
public static void main(String[] args) {
System.out.println(zaehleAufrufe(40));
}
}
【问题讨论】:
标签:
function
recursion
stack
overflow
【解决方案1】:
这几乎总是意味着没有什么可以阻止递归越来越深。无论目标是否实现,都没有达到一定水平时停止的条件。
在您的代码中,您从 40 开始,只有在您达到 23 时才会停止。但是您的一个分支正在增加数字:
return zaehleAufrufe(uebergabe-1) + zaehleAufrufe(uebergabe+1);
而且永远不会降到 23 岁。
欢迎来到堆栈溢出的 StackOverflow :)
附:最好的办法是重新考虑你的算法。如果在某种情况下您确定要使用递归,但由于依赖于未知数据,它的分支是不可预测的,您可以设置一个级别限制值。这是一个肮脏的hack,但在某些情况下它很有用。
重要的是,在此限制下,您的代码仍然会失败
- 它会尝试调用这个函数多达 2^33 次 = 大约 80 亿次,这已经足够大了 :)
public class Übung_Baeume {
static int anzAufrufe=0;
static int zahl=23;
static int max_level = 32;
static bool fault = 0;
public static int zaehleAufrufe(int uebergabe, int level)
{
if(level == max_level)
{
fault = 1;
return 0;
}
anzAufrufe++;
if (uebergabe==zahl){
return anzAufrufe;
}
return zaehleAufrufe(uebergabe-1, level+1) +
zaehleAufrufe(uebergabe+1, level+1);
}
public static void main(String[] args) {
int ret = zaehleAufrufe(40,0);
if(fault == 0)
System.out.println(ret);
else
System.out.println("Fault - recursion level limit reached!");
}
}
【解决方案2】:
ubergabe 如果不等于23 将递归ubergabe +1 和unbergabe - 1。现在每个人都会做同样的事情,所以你可以试试这个:
zaehleAufrufe(40) ; ==>
zaehleAufrufe(39) + zaehleAufrufe(41) ; ==> neither of these are 23
zaehleAufrufe(38) + zaehleAufrufe(40) + zaehleAufrufe(40) + zaehleAufrufe(42)
请注意最后一个.. 尽管其中一些最终会达到基本情况,但您会看到您在 3. 扩展中有 2 zaehleAufrufe(40)。每一个都像上面一样扩展成两个zaehleAufrufe(40),而且没有一个甚至会达到基本情况。
要使递归起作用,您需要成为更简单的问题,实际上您的问题会变成几个相同数量的问题,因此是无限递归。
要打开一个函数的次数与你只递归一次的差值一样多:
public static int zaehleAufrufe(int uebergabe)
{
anzAufrufe++;
if (uebergabe <= zahl) {
return anzAufrufe;
}
return zaehleAufrufe(uebergabe-1);
}
zaehleAufrufe(40) ; ==>
zaehleAufrufe(39) ; ==>
...
zaehleAufrufe(23) ; ==> 18