【问题标题】:Is 500 recursive calls not too much?500个递归调用是不是太多了?
【发布时间】:2014-10-25 17:30:49
【问题描述】:

Codility 的一项任务是找出二叉树的高度。该任务保证高度不会超过 500。所以想到的最简单的解决方案就是使用递归。

现在,虽然这样的解决方案通过了 Codility 中的所有测试,但我想知道我是否可以安全地假设 500 并不过分(对于任何计算机/测试平台可能是 Codility 的测试平台)或我是否应该避免递归并模拟它或以其他方式找到树的高度?

编辑: 正如 PM 77-1 所指出的,答案可能取决于我的递归是什么样子。所以我把它包括在内。定义了一个struct

struct tree {
  int x;
  tree * l;
  tree * r;
}; 

这是我的解决方案:

int getHeight(tree const * T, int height)
{
    int maxHeight = height;
    if (T->l)
    {
        maxHeight = getHeight(T->l, height + 1);
    }
    if (T->r)
    {
        maxHeight = max(maxHeight, getHeight(T->r, height + 1));
    }
    return maxHeight;
}

int solution(tree * T)
{
    return getHeight(T, 0);
}

现在我的问题是 - 知道我的解决方案是什么样子(它可以使用多少内存/等等...)并且不知道测试平台规格是什么,我可以安全地假设 500 次递归调用不会导致堆栈溢出与否?(因为如果它是 50 或 5,我想我可以放心地假设无论测试平台如何。)

编辑:我故意没有指定语言,因为 Codility 支持多种语言,如果可能的话,我想得到一个关于多个的答案。但是,我在我的解决方案中使用了 C++,所以我想这是我最感兴趣的语言。

【问题讨论】:

  • 你的问题太笼统了。并非所有的递归都是平等的。例如,如果您的递归在每次调用时都创建了一个非常大的对象,那么您可能会比 stack overflow 更早地得到 out of memory
  • 没有人可以说它对于任何计算机/测试平台来说都不算太多。对于非常旧的计算机或嵌入式系统来说可能太多了,但任何现代平台都应该毫无问题地处理它 - 另请阅读:stackoverflow.com/questions/1006867/…
  • 简短的回答是NO,你不能做出这样的假设。 任何平台都是一个巨大的要求。想想智能咖啡机上内存最少的嵌入式 Java。
  • 当然,你是对的,“任何平台”都太宽泛了。但我想到的是“任何可能成为 Codility 测试平台的平台”。

标签: recursion stack-overflow


【解决方案1】:

这取决于许多因素,包括语言和您的方法用于每次调用的堆栈空间量。

对于 Java,引用类型为 8 字节,默认堆栈大小通常为 512 kB。一个方法至少需要 1 个引用(8 个字节)来存储返回地址,以及您声明的任何变量和参数(可能每个也有 8 个字节,因为您将使用的 Java 中的大多数变量将是引用或 8 字节整数)。

让我们计算每次调用有多少堆栈空间可用。请注意,此计算忽略了程序其余部分所需的空间,并假设递归方法是堆栈中的唯一方法。我们还将假设该方法不调用自身以外的方法,因为很难说它们需要多少堆栈。实际上,您可以使用的空间会少一些。

(512000 bytes) / (500 calls) = 1024 bytes per call
(1024 bytes per call) / (8 bytes per reference) = 128 references per call

因此,对于 500 级递归,在堆栈空间用完之前,您的方法中可以有 127 个变量和参数(因为我们为返回地址减去了 1)。即使有这些假设,您似乎也不太可能达到这个限制。

【讨论】:

  • 这正是我正在寻找的答案!但是,在接受之前,我会等着看其他人是否可以提供有关其他编程语言的一些信息。或者也许你可以?
  • 某些语言将进行优化以减少递归方法调用的堆栈使用量。您不会找到一种语言在每次方法调用时消耗的堆栈比 Java 多得多,因为这几乎是普遍的行为。堆栈大小和参考大小也会有所不同。例如,如果您有 32 位操作系统,某些语言,如 C(但不是 Java,因为它使用虚拟机)将具有 32 位(4 字节)引用。在这种情况下,您可以在相同数量的堆栈空间上存储更多引用。在任何情况下都无法保证确切的堆栈空间是多少。
猜你喜欢
  • 1970-01-01
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 2010-09-22
  • 2011-11-11
  • 1970-01-01
相关资源
最近更新 更多