由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - 尾递归不会导致堆栈溢出吗?
相关主题
递归程序C语言的变量都一定要放在stack上吗?
丰田在嵌入式系统里用递归有人发过的一个面试题
Dynamic programming和backtracking有什么区别吗Initialization list的一个问题
新手问,大家平时使用recursion么?感觉很酷啊问个C++编译器如何处理函数内的static 变量
急问大牛们:关于fortran堆栈溢出问个内存的问题
请教一个递归程序的问题问个C++ 编译器临时变量的问题 (转载)
inline function是否可以递归?Is this a poor practice?
所谓FP就是 递归+pattern matching?以下两个C 代码是不是完全等价?
相关话题的讨论汇总
话题: int话题: return话题: factorial
进入Programming版参与讨论
1 (共1页)
s******y
发帖数: 172
1
基础薄弱哈,请勿见笑。
最近在上udemy上的C++算法课:https://www.udemy.com/algorithms-bootcamp-in-c/
这个老师说尾递归不需要堆栈,并举了求阶乘的两个例子对比:
int factorial(int n) {
if (n == 1) return 1;
return n * factorial(n - 1);
}
int factorialAccumulator(int n, int accumulator) {
if (n == 1) return accumulator;
return factorialAccumulator(n - 1, n * accumulator);
}
他说factorialAccumulator()这样就不会用到堆栈了。我死活想不明白怎么就不需要了
。他说得对吗?大牛们能解释一下吗?
多谢!
s******y
发帖数: 172
2
他之后又举了例子,说factorial()这样写就可以清楚地看出需要堆栈了:
int factorial(int n) {
if (n == 1) return 1;
m = n * factorial(n - 1);
return m;
}
那我就奇怪了,factorialAccumulator()也可以这样处理啊,他就不提了。
int factorialAccumulator(int n,int accumulator) {
if (n == 1) return accumulator;
m = factorialAccumulator(n - 1, n * accumulator);
return m;
}

【在 s******y 的大作中提到】
: 基础薄弱哈,请勿见笑。
: 最近在上udemy上的C++算法课:https://www.udemy.com/algorithms-bootcamp-in-c/
: 这个老师说尾递归不需要堆栈,并举了求阶乘的两个例子对比:
: int factorial(int n) {
: if (n == 1) return 1;
: return n * factorial(n - 1);
: }
: int factorialAccumulator(int n, int accumulator) {
: if (n == 1) return accumulator;
: return factorialAccumulator(n - 1, n * accumulator);

r****t
发帖数: 10904
3
如果返回值直接被返回的话,编译器能把这一层调用给优化掉。

【在 s******y 的大作中提到】
: 他之后又举了例子,说factorial()这样写就可以清楚地看出需要堆栈了:
: int factorial(int n) {
: if (n == 1) return 1;
: m = n * factorial(n - 1);
: return m;
: }
: 那我就奇怪了,factorialAccumulator()也可以这样处理啊,他就不提了。
: int factorialAccumulator(int n,int accumulator) {
: if (n == 1) return accumulator;
: m = factorialAccumulator(n - 1, n * accumulator);

m*****n
发帖数: 3575
4
本版的忙碌大佬都觉得回答人的问题是被占便宜,吼吼~
T*******x
发帖数: 8565
5
我觉得是编译器优化的问题,这两种写法的最显著区别是,accumulator的写法不需要
存函数返回值,因为return的就只是函数返回值,没有用函数返回值再进行计算,这样
的写法编译器就容易优化它。

【在 s******y 的大作中提到】
: 基础薄弱哈,请勿见笑。
: 最近在上udemy上的C++算法课:https://www.udemy.com/algorithms-bootcamp-in-c/
: 这个老师说尾递归不需要堆栈,并举了求阶乘的两个例子对比:
: int factorial(int n) {
: if (n == 1) return 1;
: return n * factorial(n - 1);
: }
: int factorialAccumulator(int n, int accumulator) {
: if (n == 1) return accumulator;
: return factorialAccumulator(n - 1, n * accumulator);

j*****w
发帖数: 1
6
这个:
int factorial(int n) {
if (n == 1) return 1;
m = n * factorial(n - 1);
return m;
}
用了临时变量。而临时变量是需要栈空间的。所以栈会增长。
s******y
发帖数: 172
7
可如果写成:
int factorialAccumulator(int n,int accumulator) {
if (n == 1) return accumulator;
m = factorialAccumulator(n - 1, n * accumulator);
return m;
}
也会用到临时变量。是否编译器很聪明,觉得这个临时变量用不上就消了?

【在 j*****w 的大作中提到】
: 这个:
: int factorial(int n) {
: if (n == 1) return 1;
: m = n * factorial(n - 1);
: return m;
: }
: 用了临时变量。而临时变量是需要栈空间的。所以栈会增长。

j*****w
发帖数: 1
8
Depends on the compiler you are using.

【在 s******y 的大作中提到】
: 可如果写成:
: int factorialAccumulator(int n,int accumulator) {
: if (n == 1) return accumulator;
: m = factorialAccumulator(n - 1, n * accumulator);
: return m;
: }
: 也会用到临时变量。是否编译器很聪明,觉得这个临时变量用不上就消了?

s****x
发帖数: 22
9
即使不用临时变量,也需要把返回地址入栈。所以从理论上来说,所有的递归都有堆栈
溢出的问题,用的局部变量越多,溢出得越快。

【在 j*****w 的大作中提到】
: 这个:
: int factorial(int n) {
: if (n == 1) return 1;
: m = n * factorial(n - 1);
: return m;
: }
: 用了临时变量。而临时变量是需要栈空间的。所以栈会增长。

n*****3
发帖数: 1584
10
https://www.google.com/search?rlz=1C1GCEU_enUS838US838&ei=ZLK8XPT1DtHI_
Qadyqu4DA&q=%E5%B0%BE%E9%80%92%E5%BD%92%E4%BC%98%E5%8C%96&oq=%E5%B0%BE%E9%80
%92%E5%BD%92+&gs_l=psy-ab.1.0.0i67l4j0i12l3j0l2.1386.1386..3374...0.0..0.70.
70.1......0....1..gws-wiz.......0i71.7tm4eEc3iGo

【在 s******y 的大作中提到】
: 基础薄弱哈,请勿见笑。
: 最近在上udemy上的C++算法课:https://www.udemy.com/algorithms-bootcamp-in-c/
: 这个老师说尾递归不需要堆栈,并举了求阶乘的两个例子对比:
: int factorial(int n) {
: if (n == 1) return 1;
: return n * factorial(n - 1);
: }
: int factorialAccumulator(int n, int accumulator) {
: if (n == 1) return accumulator;
: return factorialAccumulator(n - 1, n * accumulator);

相关主题
inline function是否可以递归?有人发过的一个面试题
所谓FP就是 递归+pattern matching?Initialization list的一个问题
C语言的变量都一定要放在stack上吗?问个C++编译器如何处理函数内的static 变量
进入Programming版参与讨论
g*******u
发帖数: 3948
11
好像 大的问题不建议用递归的
而是改成 循环的非递归方式
z*y
发帖数: 1311
12

It depends on the optimization option of the compiler. Without optimization,
it may still use stack even without temporary.

【在 s******y 的大作中提到】
: 基础薄弱哈,请勿见笑。
: 最近在上udemy上的C++算法课:https://www.udemy.com/algorithms-bootcamp-in-c/
: 这个老师说尾递归不需要堆栈,并举了求阶乘的两个例子对比:
: int factorial(int n) {
: if (n == 1) return 1;
: return n * factorial(n - 1);
: }
: int factorialAccumulator(int n, int accumulator) {
: if (n == 1) return accumulator;
: return factorialAccumulator(n - 1, n * accumulator);

T*******x
发帖数: 8565
13
嗯。这个是对的。
比如现在执行factorial(n=5),这个n就是临时变量,而且不能马上投入计算,因为要
先算factorial(4),所以n=5这个值要先存起来。同理算factorial(n=4)时,n=4又要存
起来,这样栈就在增长。

【在 j*****w 的大作中提到】
: 这个:
: int factorial(int n) {
: if (n == 1) return 1;
: m = n * factorial(n - 1);
: return m;
: }
: 用了临时变量。而临时变量是需要栈空间的。所以栈会增长。

T********i
发帖数: 2416
14
tail call目前最容易优化的是类似这个
function f(args)
...
return g(args2)
end
比如
function factt(n) return fact_(n, 1) end
function fact_(n, ans) if (n==0) then return ans else return fact_(n-1, n*
ans) end end
m*****n
发帖数: 3575
15
我记得Python规定堆栈最多不能超过1000层?
好像就是针对你说的这个递归叠递归危险
l*******m
发帖数: 1096
16
1000是个default的环境变量,你可以改。比如你担心手下用了递归,你把它改到很小
,看看有没有runtime error

【在 m*****n 的大作中提到】
: 我记得Python规定堆栈最多不能超过1000层?
: 好像就是针对你说的这个递归叠递归危险

r****t
发帖数: 10904
17
python 尾递归没有优化过,GvR 否了。

【在 m*****n 的大作中提到】
: 我记得Python规定堆栈最多不能超过1000层?
: 好像就是针对你说的这个递归叠递归危险

1 (共1页)
进入Programming版参与讨论
相关主题
老码农冒死揭开行业黑幕:如何编写无法维护的代码(zz)急问大牛们:关于fortran堆栈溢出
如何计算1000的阶乘请教一个递归程序的问题
请教一个作用域的问题inline function是否可以递归?
[合集] 请问关于堆栈的问题所谓FP就是 递归+pattern matching?
递归程序C语言的变量都一定要放在stack上吗?
丰田在嵌入式系统里用递归有人发过的一个面试题
Dynamic programming和backtracking有什么区别吗Initialization list的一个问题
新手问,大家平时使用recursion么?感觉很酷啊问个C++编译器如何处理函数内的static 变量
相关话题的讨论汇总
话题: int话题: return话题: factorial