// Recursive Implementation:
int factorialResult(int n) {
if (n == 0) {
return 1;
}
else {
return factorialResult(n - 1) * n;
}
}
// Iterative Implementation:
int factorialResult(int n) {
int factorialSum = 1;
for (int i = 1; i <= n; i++) {
factorialSum *= i;
}
return factorialSum;
}
在大多数情况下,递归函数实现使用更多的内存吗?如果是这样的话,它是否是相应迭代函数实现的内存的两倍?
2条答案
按热度按时间6gpjuf901#
在您的阶乘实现中,没有使用堆内存空间,因此在这方面,两者是相同的。它们 * 可能 * 不同的地方在于堆栈空间使用。
递归的解决方案是O(n)在堆栈空间的使用,而迭代的解决方案使用常数堆栈空间。给定足够的递归调用,递归解决方案可能会产生堆栈溢出错误。
这里有几个条件:
1.你的编译器 * 可以 * 实现尾调用优化,如果你的函数中的最后一个(或“尾”)调用只是另一个函数调用,编译器可以将其转换为一个简单的循环。
例如
这就是所谓的
factorialResult_tailRec(5, 1)
。然而,这种优化不应该被指望。
1.仔细考虑您的数据类型。在遇到堆栈溢出之前,您可能会溢出
int
。比如,13!已经溢出了32位int
,但是那些递归调用对堆栈空间没有实质性的影响。即使你将数据扩展到64位整数,21!仍然溢出并且对堆栈空间没有显著影响。gwbalxhn2#
不是“两倍多”的内存,而是可能使用的
n
倍的内存。所有这些内存都是堆栈内存。与堆内存相比,堆栈内存的分配成本更低。堆栈分配需要O(1)时间-它只是移动堆栈指针。
但它是有限的。线程通常在高端计算机上有一兆字节的堆栈,在低端设备上大约有100 KB。取决于编译器设置和操作系统架构。因此,如果调用递归
factorial(500000)
,在溢出的结果返回给调用者之前,它会遇到一个字面上的“堆栈溢出”错误。