在“像程序员一样思考”一书中,下面的递归函数被称为“非常低效”,我无法弄清楚为什么(这本书没有解释)。似乎没有任何不必要的计算。是因为调用这么多函数(多次使用相同的函数)的开销,从而为每次调用函数设置环境?
int factorial(int n) {
if (n == 1) return 1;
else return n * factorial(n-1);
}
答案 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