回 帖 发 新 帖 刷新版面

主题:[原创]小试递归算法与循环算法在Fibonacci数列求解中的运算效率

前言:可能太初级了,如果版主感觉层次太低删掉或丢到初学园地里。

小试递归算法与循环算法在Fibonacci数列求解中的运算效率

作者:KKND
时间:2004年9月1日

源程序代码如下:

//  Fibonacci数列第N项求解算法对比程序,VC 6.0 编译通过

#include <iostream.h>

long fib1(int n);
long fib2(int n);

int i=0;  //运算次数计数器


//---------------start main()------------
void main()
{
    int n=0;

    cout<<"Input a int number:";        //显示提示信息
    cin>>n;                    //输入参数 n
    
    cout<<endl<<endl;            //显示两个空行

    //测试使用递归算法的情况------------------

    i=0;  //运算次数计数器清零

    cout<<"fib1("<<n<<")="<<fib1(n)<<endl;//输出结果
    cout<<"  Times="<<i<<" (Call Back Times!) "<<endl;//输出计算次数
    cout<<endl;

    //结果表明运算效率相当差,递归调用的次数居然达到了运算结果数值的2倍-1次。
    //在n=20的情况下调用次数竞达到13529次。
    //不过从中得到的启示是,是否可以利用这个规律得出通用的计算公式。
    //即   计算结果=(递归调用次数+1)/2


    //测试使用循环算法的情况------------------

    i=0;  //运算次数计数器清零

    cout<<"fib2("<<n<<")="<<fib2(n)<<endl;//输出结果
    cout<<"  Times="<<i<<" (Loop Times!) "<<endl;//输出计算次数
    cout<<endl;

    //结果表明运算效率很高,总运算次数连前面的条件判断加起来只有 n 次
    //在n=20的情况下只需要循环18次,连2次判断可认为计算20次。

}//----------------end main()--------------


//---------------start fib2()------------
long fib1(int n)    //利用递归调用
{    
    i++;                    //运算次数计数器,不计入算法复杂性统计。
    switch(n)               //
    {                        //
        case 0:return 0;    //-----每次调用时都无法跳过的判断运算(复杂性不明)。
        case 1:                //
        case 2:return 1;    //
    }                        //
    
    return fib1(n-1)+fib1(n-2);        //主要计算语句,每次调用有两次加法等效运算和一次返回(至少相当于赋值),而且还要进行递归调用(复杂性不明)。
}//--------------end fib1()--------------


//---------------start fib2()------------
long fib2(int n)    //利用循环语句
{    
    int k=0;
    long a=1,b=1,c=0;
    
    if(n==0)            //根据n值不同可算做1至3次判断运算计入算法复杂性。
    {                    //
        return 0;        //
    }                    //
    else if(n==1||n==2)    //--|
    {                    //  |
        return 1;        //  |---若考虑通用性,此初始条件判断可以移入循环体,但效率将不是最优化,
    }                    //--|   移入循环体会在每次循环增加1至2次判断运算,增加了算法复杂性。
    else
    {
        for(k=2;k<n;k++)
        {
                  
            b=a+(c=b);    //
            a=c;        //(或写成c=b;b=a+b;a=c;)实际运算语句,只有一个加法和三个赋值。
        
            i++;        //运算次数计数器,不计入算法复杂性统计。
        }
        return b;
    }
}//--------------end fib2()--------------


/*上面的fib2()代码精简形式如下:

long fib2(int n){
    int k=0;
    long a=1,b=1,c=0;

    if(n==0)
        return 0;
    if(n==1||n==2)
        return 1;
    for(k=2;k<n;k++){
        b=a+(c=b);a=c;
    }
    retrun b;
}
------------------*/

QQ:20587039
E-mail: li-Q_Q@163.com

回复列表 (共20个回复)

11 楼

来消除一些误区。
手动用栈来模拟递归的效率并不会比系统的调用栈快。而且递归并不是效率差的原因,重复计算才是。参见我楼上的回复。

12 楼

不好意思,是我没说清楚,我所发表的看法都是基于两点的:1,数据量足够大时,同等情况下的效率比较。2,我所指的挥霍内存肯定指的是栈堆所占的那一部分内存。
若说法还有问题,欢迎指出。[em2]

13 楼

关于第一点
你要实现还是需要入栈出栈,你用非递归就要自己手动处理,但递归是系统自动进行的。哪个快?这个跟数据量大小无关吧?再大的数你也得手动处理,再大的数递归也可以让系统自动进行。

关于第二点,既然你说了你指的是堆栈,也就不说什么了。
不过,递归完成后堆栈会自然而然地变空,没发现有什么费的。而且,tc里的栈空间最多是640k,占很大内存吗?tp里的栈空间最大只有65520字节,占多大?64k都不到吧。

14 楼

用通项公式啊!你们不知道有通项公式吗

15 楼

F(n)=((1+sqrt(5))^n-(1-sqrt(5))^n)/(2^n*sqrt(5))

16 楼

求助6*6 36个数 分别填入1到6,必须有6个1,6个2,6个3,6个4,6个5,6个6,谁能帮我有赏啊!

17 楼

汗!~~~~~今天作程序的时候用递归做,结果死机!!!!!暴汗~~~~~~~~我才用1700多个序列作测试啊!只好推倒重来!!!!唉~~~建议以后用递归的思想自己求解,具体实现还是表用递归吧!

18 楼

[em9][em9][em9]
强烈鄙视用c++写 不用算法写
[em16][em16][em16][em16][em16][em16][em16][em16]

19 楼

麻烦不要把书上的例题拿出来眩

20 楼

楼主的程序真的编译通过了?
搞笑啊
我看错误不少啊

我来回复

您尚未登录,请登录后再回复。点此登录或注册