递归优化——尾递归果然给力
2011-08-05 22:33
417 查看
这几天又翻出一本《C++大学教程·第五版》看,看着看着就看到Fibonacci数列,很简单就写了个递归想算一下,代码非常朴素,但是没想到居然这么慢,加上个GetTickCount()函数一看,算到第40个数就耗费了大约31秒的时间,实在让人汗颜,在网上搜索了一把,发现了本文http://blog.zhaojie.me/2009/03/tail-recursion-and-continuation.html,大为惊叹,原来递归也是可以优化的,稍微修改了一下变为尾递归再计算,居然只需31毫秒,1000倍啊!
上面那个链接老赵写的很好,我就不浪费口水了,给出朴素的代码和优化后的代码充一下字数吧。
朴素的递归计算Fibonacci数列:
转变为尾递归之后的代码:
fibonacci(n-1,acc2,acc1+acc2)真是神来之笔,原本朴素的递归产生的栈的层次像二叉树一样,以指数级增长,但是现在栈的层次却像是数组,变成线性增长了,实在是奇妙,总结起来也很简单,原本栈是先扩展开,然后边收拢边计算结果,现在却变成在调用自身的同时通过参数来计算。
上面那个链接老赵写的很好,我就不浪费口水了,给出朴素的代码和优化后的代码充一下字数吧。
朴素的递归计算Fibonacci数列:
#include <iostream> #include <ctime> #include <windows.h> using std::cout; using std::endl; unsigned fibonacci(int n) { if (n < 2) { return n; } else { return fibonacci(n-1)+fibonacci(n-2); } } int main() { DWORD tt; int i; tt = GetTickCount(); for (i = 1; i < 41; i++) { cout << i << "\t" << fibonacci(i) << endl; } cout << "It takes you " << GetTickCount() - tt << "ms to work it out." << endl; return 0; }
转变为尾递归之后的代码:
#include <iostream> #include <ctime> #include <windows.h> using std::cout; using std::endl; unsigned fibonacci(int n,unsigned acc1,unsigned acc2) { if (n < 2) { return acc1; } else { return fibonacci(n-1,acc2,acc1+acc2); } } int main() { DWORD tt; int i; tt = GetTickCount(); for (i = 1; i < 41; i++) { cout << i << "\t" << fibonacci(i,1,1) << endl; } cout << "It takes you " << GetTickCount() - tt << "ms to work it out." << endl; return 0; }
fibonacci(n-1,acc2,acc1+acc2)真是神来之笔,原本朴素的递归产生的栈的层次像二叉树一样,以指数级增长,但是现在栈的层次却像是数组,变成线性增长了,实在是奇妙,总结起来也很简单,原本栈是先扩展开,然后边收拢边计算结果,现在却变成在调用自身的同时通过参数来计算。
相关文章推荐
- 递归优化之尾递归
- 递归及尾递归优化
- Maximum function nesting level of '100' reached, aborting!--漫谈递归:PHP里的尾递归及其优化
- js递归的优化(尾递归)
- [Java 8] (8) Lambda表达式对递归的优化(上) - 使用尾递归
- 漫谈递归:从汇编看尾递归的优化
- 3分钟Tips:递归的优化|尾递归
- 递归性能优化之尾递归~
- [Java 8] (8) Lambda表达式对递归的优化(上) - 使用尾递归 .
- 递归 尾递归
- 第一篇:浅析线性递归和尾递归
- hdoj 1028 Ignatius and the Princess III <递归+状态记录优化----母函数????>
- 递归与尾递归总结
- 动态规划入门-数字三角形(从朴素递归到各种优化)
- 网站优化之如何让友链更给力
- 青蛙跳台阶--尾递归优化
- ## 递归与尾递归 ##
- 漫谈递归:PHP里的尾递归及其优化
- [Java 8] (9) Lambda表达式对递归的优化(下) - 使用备忘录模式(Memoization Pattern) .
- 【Java】斐波那契数列(Fibonacci Sequence、兔子数列)的3种计算方法(递归实现、递归值缓存实现、循环实现、尾递归实现)