zoukankan      html  css  js  c++  java
  • 递归优化——尾递归果然给力

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

  • 相关阅读:
    面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?请根据自己的理解简明扼要的回答
    当下大部分互联网创业公司为什么都愿意采用增量模型来做开发?
    0
    计算机网络
    java基础
    java 多线程编程
    java类与对象,用程序解释
    修饰符的探讨
    java学习总结02
    java day1
  • 原文地址:https://www.cnblogs.com/pianoid/p/2129077.html
Copyright © 2011-2022 走看看