【问题标题】:What is the common industry practice regarding recursion? Or how do we know if we should avoid recursion altogether? [closed]关于递归的常见行业惯例是什么?或者我们怎么知道我们是否应该完全避免递归? [关闭]
【发布时间】:2020-07-15 13:38:42
【问题描述】:

我确实理解递归的问题之一是堆栈深度,它可能导致非常深的递归出现问题。我也知道递归可以被显式堆栈使用代替以避免此类问题。
另一方面,递归允许代码简洁明了(我会说很漂亮),如果我没记错的话,它是所有标准教科书中介绍算法的主要方式。

我的问题比理论更实际:

我正在运行以下程序来计算在获得java.lang.StackOverflowError之前我能走多远
我的理由是,例如如果我有一个包含几千个顶点的小型图形视图,并且每次遍历的处理量最少,那么递归与迭代方法可能就没有那么重要了:

public static void foo(int i) {
   if (i % 5000 == 0) {
        System.out.println(i);
   }
   foo(i + 1);
}

public static void main(String[] args) {
    foo(0);
}

输出是:

Exception in thread "main" java.lang.StackOverflowError
5000
10000

因此,我的解释是,程序会在处理超过 10000 个顶点后进行 DFS,这听起来很小。
谷歌搜索我发现当我们运行一个程序时,堆栈的默认大小是可以配置的,但我想知道这方面的行业惯例是什么?

是否为繁重的服务器程序设置显式线程堆栈大小,以便上面的示例在实践中不会成为问题?还是完全避免编写递归?还是我的例子不能真正代表一个问题?

更新
我明白上面的代码示例是一个无限递归。这样做的唯一目的是看看它在断裂之前能走多远。

【问题讨论】:

  • 您发布的代码是无限递归。没有任何配置可以让它工作。
  • @khelwood:是的,我明白这一点。唯一的目的是看看它在崩溃之前能走多远。没有别的
  • 据我所知,没有行业惯例,但是当您没有支持尾调用消除的语言时,最好避免递归调用。除非,也就是说,您知道递归非常浅。
  • 代码干净简洁是因为它清晰简洁,而不是因为它是“递归编写的”。而且它也不能使它成为好的代码。例如,将斐波那契函数( 教科书递归的典型代表)作为递归函数实现是现实生活中最糟糕的实现,这适用于许多其他不关心自己的教科书示例他们提供的代码是否是高效的。只要保证递归本身足够浅,递归就有它的位置,并且递归的开销是微不足道的。
  • @Jim 你是对的。我会投票重新开放。

标签: java algorithm recursion optimization graph-algorithm


【解决方案1】:

是否为繁重的服务器程序设置显式线程堆栈大小,这样上面的示例在实践中就不会成为问题?

没有。

  1. 示例是无限递归。这永远是个问题。
  2. Java 中没有足够大的堆栈大小。它需要无限量的堆栈空间。
  3. (在实现“尾调用优化”的语言/实现中,不会出现堆栈溢出。但 Java 不是这样的语言。)

还是完全避免编写递归?

没有。递归很好……只要你能预测递归的最大深度。

或者我的例子不能真正代表一个问题?

没有真正的代表性。

然而,在现实世界中显然存在递归方法会因某些输入而失败的问题。

谷歌搜索发现,当我们运行程序时,堆栈的默认大小是可以配置的,但我想知道这方面的行业惯例是什么?

设置默认堆栈大小没有相关的“行业惯例”。所需的堆栈大小取决于实际算法及其实现以及输入数据。

但是,当您无法对递归深度设置合理界限时,尝试实施递归解决方案是一个坏主意


对于给定的 Java 程序,计算给定递归深度所需的堆栈空间在技术上是可行的,但计算将取决于平台。

JVM 对最大堆栈大小设置了限制。例如,对于 64 位模式的 x86-64 上的 Java 11,您不能将 -Xss 设置为大于 1g。 (这可能是件好事。)

【讨论】:

  • when you cannot place a reasonable bound on the depth of recursion. 这很有帮助。现在我可以看到进行良好的复杂性评估的价值。这有帮助,谢谢
【解决方案2】:

粗略的经验法则是,一旦调用次数达到数百次,我就会对递归感到不舒服。几千肯定太高了。

递归非常适用于 O(log n) 调用深度的问题,例如二叉树遍历,因为对数的扩展非常缓慢。我不会将它用于 O(n) 图算法。

【讨论】:

  • 这是对logN的一个很好的见解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2010-09-05
相关资源
最近更新 更多