zoukankan      html  css  js  c++  java
  • 关于递归

    递归算法一般用于解决三类问题:
    (1)数据的定义是按递归定义的。(Fibonacci函数)

        斐波那契数列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...,数列中从第三项起,每一项都是前两项之和。


    (2)问题解法按递归算法实现。
        这类问题虽则本身没有明显的递归结构,但用递归求解比迭代求解更简单,如Hanoi问题。


    (3)数据的结构形式是按递归定义的。
        如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归地描述。

    请不要这样写递归:

    #include<iostream>
    using namespace std;
     
    int F(int n)//函数返回一个数对应的Fibonacci数
    {
    	if(n==0 || n==1)//递归边界
    		return 1;
    	return F(n-1) + F(n-2);//递归公式
    }
     
    int main()
    {
    	//测试
    	int n;
    	while(cin >> n)
    		cout << F(n) << endl;
     
    	return 0;
    }
    

      

    上述代码在计算比较大的数时,有严重的效率问题,可以算作逻辑bug了,为计算第40个斐波那契数,递归被调用了3亿多次,计算第50个斐波那契数,调用函数400多亿次……

    问题出在这里:

    .

    return F(n-1) + F(n-2);
    

      

    因为每次计算都需要在堆栈中缓存前两次的结果,导致堆栈使用急剧增大,很快就耗尽系统/虚拟机内存。总计算次数(正比于所需堆栈大小,可粗略估计为n!)可以写代码验证:

        long total = 0;
        long a = 1;
        long b = 1;
        for (int i = 0; i <= 50; i++) {
            if (i < 2) {
                total += 1;
                continue;
            }
            long tmp = b;
            b = a + b + 1;
            a = tmp;
            cout << b << endl;
        }
    

    为计算第50个斐波那契数,需要递归调用函数F()的次数是40730022147次。

    这个例子告诉我们,在递归中调用自身超过一次都是有问题的,应尽力避免。

    解决这个问题只需避免多余的出入栈操作,可参考下述代码,这样可以把所需堆栈大小降为正比于n:

    #include<iostream>
    
    using namespace std;
    
    long a = 0;
    long b = 1;
    
    long fibs(int n) {
        if (n == 0 || n == 1){
            return b;
        }
        long tmp = b;
        b = b + a;
        a = tmp;
        return fibs(n - 1);
    }
    
    int main() {
        cout << fibs(90) << endl;
        return 0;
    }
    

      

  • 相关阅读:
    能大大提升工作效率和时间效率的9个重要习惯
    hibernate的校验
    8. semahpore原理
    chklist
    android textview 自动换行 整齐排版
    fiddler接口测试,js代码修改日志展示(埋点用)
    Python模块之 tqdm进度条
    Python抓取网页到本地
    Python模块之 clint 进度条
    python windows下pip安装错误whl文件安装错误
  • 原文地址:https://www.cnblogs.com/areful/p/9315273.html
Copyright © 2011-2022 走看看