为什么这个阶乘递归函数效率低下?

时间:2013-12-12 04:17:02

标签: c++ recursion

在“像程序员一样思考”一书中,下面的递归函数被称为“非常低效”,我无法弄清楚为什么(这本书没有解释)。似乎没有任何不必要的计算。是因为调用这么多函数(多次使用相同的函数)的开销,从而为每次调用函数设置环境?

int factorial(int n) {
  if (n == 1) return 1;
  else return n * factorial(n-1);
}

4 个答案:

答案 0 :(得分:6)

从两个方面来说效率很低,你打了其中一个:

它是递归的,而不是迭代的。如果未启用尾调用优化,则效率非常低。 (要了解有关尾部调用优化的更多信息,请查看here。)可以这样做:

int factorial(int n)
{
    int result = 1;
    while (n > 0)
    {
        result *= n;
        n--;
    }
    return result;
}

或者,for循环。

但是,正如上面的评论中所指出的,如果int甚至无法保持结果,那么效率并不重要。它应该是long s,long long s,甚至是大头。

第二个低效率就是没有一个有效的算法。 This list of factorial algorithms通过减少数值运算的数量,展示了一些更有效的计算阶乘的方法。

答案 1 :(得分:0)

当不使用实现尾调用优化的编译器时,C中存在重要的函数调用开销。

函数调用开销是计算机正确设置函数调用所需的额外时间和内存。

尾调用优化是一种将递归函数转换为循环函数的方法。

答案 2 :(得分:0)

我认为书作者可能想告诉读者不要滥用递归。对于此功能,您可以使用:

int factorial(int n) {
    int res = 1; 
    for (i = 1; i <= n; i++) {
        res = res * i;
    }
    return res;
}

答案 3 :(得分:0)

就内存堆栈而言,递归速度和内存消耗速度一样慢。这是一个将信息推送到堆栈并再次弹出它的时间。递归的主要优点是它使算法更容易理解或更“优雅”。

为了找到阶乘,我们可以使用For循环,它在内存和时间复杂度方面都很好。

int num=4;
int fact = 1;
for (;num>1;num--)
{
fact = fact*num;   
}
//display fact