递归优化——尾递归果然给力

  这几天又翻出一本《C++大学教程·第五版》看,看着看着就看到Fibonacci数列,很简单就写了个递归想算一下,代码非常朴素,但是没想到居然这么慢,加上个GetTickCount()函数一看,算到第40个数就耗费了大约31秒的时间,实在让人汗颜,在网上搜索了一把,发现了本文http://blog.zhaojie.me/2009/03/tail-recursion-and-continuation.html,大为惊叹,原来递归也是可以优化的,稍微修改了一下变为尾递归再计算,居然只需31毫秒,1000倍啊!

  上面那个链接老赵写的很好,我就不浪费口水了,给出朴素的代码和优化后的代码充一下字数吧。

  朴素的递归计算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)真是神来之笔,原本朴素的递归产生的栈的层次像二叉树一样,以指数级增长,但是现在栈的层次却像是数组,变成线性增长了,实在是奇妙,总结起来也很简单,原本栈是先扩展开,然后边收拢边计算结果,现在却变成在调用自身的同时通过参数来计算。

posted @ 2011-08-05 22:33  pianoid  阅读(1811)  评论(0编辑  收藏  举报