500个递归调用不是太多了吗?

时间:2014-10-07 23:55:04

标签: recursion stack-overflow

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 ++,所以我猜这是我最感兴趣的语言。

1 个答案:

答案 0 :(得分:2)

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

对于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的返回地址)。即使有了这些假设,你也不太可能达到这个限制。