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

  • 相关阅读:
    TCP带外数据
    ASP.Net Core 返回的json数据,自定义日期格式
    C# 简单的区块链实现
    PowerShell自动部署ASP.NET Core程序到 IIS
    ASP.NET Core依赖注入多个服务实现类
    EF Core 2.0 执行原始查询如何防止SQL注入
    C#7 进入快速迭代道路
    QuartzNet 任务管理系统
    WebApi如何传递参数
    C# 快速高效率复制对象另一种方式 表达式树
  • 原文地址:https://www.cnblogs.com/pianoid/p/2129077.html
Copyright © 2011-2022 走看看