首页
社区
课程
招聘
[讨论]尾递归~
发表于: 2010-5-25 10:41 5810

[讨论]尾递归~

2010-5-25 10:41
5810
今天才听说有个编程技巧叫做尾递归,据说比传统递归效率高些。

算阶乘的传统递归代码:
# include <stdio.h>

int fun (int n){

        return (n <= 1) ? 1 : n * fun (n - 1) ;

}

void main (){

        printf ("%d\n", fun (5)) ;

}

分析:
过程展开如下
        fun (5)
=>        5 * fun (4)
=>        5 * 4 * fun (3)
=>        5 * 4 * 3 * fun (2)
=>        5 * 4 * 3 * 2 * fun(1)
=>        5 * 4 * 3 * 2 * 1
=>        5 * 4 * 3 * 2
=>        5 * 4 * 6
=>        5 * 24
=>        120

算阶乘的尾递归代码:
# include <stdio.h>

int fun (int n, int a){

        return (n <= 1) ? a : fun (n-1, a*n) ;

}

void main (){

        printf ("%d\n", fun (5, 1)) ;

}

分析:
过程展开如下
        fun (5,1)
=>        fun (4, 5)
=>        fun (3, 20)
=>        fun (2, 60)
=>        fun (1, 120)
=>        120

直觉上觉得尾递归确实好一点,但是不能说服自己。请各位看看,讨论讨论,这个方式究竟好不好,好在哪,怎么好~~谢谢

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (11)
雪    币: 4580
活跃值: (992)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
普通递归容易栈溢出,就是栈空间耗尽,为递归无此忧虑
2010-5-25 11:17
0
雪    币: 962
活跃值: (1686)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这个是依赖于编译器优化的
2010-5-25 14:09
0
雪    币: 358
活跃值: (662)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
此话怎讲?....
2010-5-25 14:19
0
雪    币: 157
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
2楼能否详细一点~?

同4楼问。
2010-5-25 20:02
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
普通递归容易栈溢出,就是栈空间耗尽,为递归无此忧虑

没看出来,2楼详解一下吧
2010-5-26 20:51
0
雪    币: 276
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
用 OD 跟踪一下,注意下堆栈的变化就啥都清楚了,呵呵。
2010-5-26 23:23
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
8
tail recursion, 不是可以转换为一个循环语句么?
2010-5-27 21:37
0
雪    币: 356
活跃值: (38)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
9
如果编译器不优化应该不会有提速吧。
递归只有在做重复工作时效率才会降低。比如
return fun(n - 1) * func(n - 2)
fun(n - 1)和func(n - 2)相当与把 n - 2 后的重复数据计算了两次,层数越多重复计算也越多。
LZ这种我没看出来会提速。

递归提速用动态规划比较好。让递归边计算边把中间结果记录下来,下一次计算时可以直接使用。
2010-5-28 09:12
0
雪    币: 358
活跃值: (662)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
10
按理论说,所以有的递归都可以转成循环的!
2010-5-28 13:47
0
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
gcc开O2级别优化的话就可以将递归调用中call换成jmp,减少开销.

尾递归一般在FP编程(Scheme, Erlang)里面,主要编译器会识别出尾递归,从而进行优化(可能就被优化成一次循环)。

在C里面完全没有必要。编译器会对递归进行优化
Ps:Python虽然支持FP部分特性,但是未对尾递归进行优化的。具体原因Python作者Guido博客上有写原因。
2010-10-13 10:47
0
雪    币: 246
活跃值: (81)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
递归占用大量栈,还有就是速度慢
2010-10-13 12:54
0
游客
登录 | 注册 方可回帖
返回
//