zoukankan      html  css  js  c++  java
  • 尾递归和线性递归

    1、递归的定义

    • 函数直接或间接的调用自己
    • 使用递归时,必须有明确的结束递归的条件

    2、递归的适用场合

    • 数据的定义按照递归定义(比如求n!)
    • 问题的解法适用于使用递归
    • 数据的结构是按递归定义的(比如二叉树)

    3、线性递归

      也就是普通递归,下一次递归数据的计算要依赖于上一次递归的结果和参数,当数据量较小时执行效率与尾递归几乎没区别,但当数据量较大,迭代次数较多时,由于每次递归都要在内存中开辟一个栈空间,用来存储上次递归的结果和参数,这样的算法将导致严重的内存开销,甚至造成内存溢出,抛出java.lang.StackOverflowError,下面用线性递归实现斐波那契数列。

      /**

    * 线性递归实现斐波拉契数列

    * @param month

    */

    public  int fblq(int month){

    if(month<3){

    return 1;

    }

    return fblq(month-1)+fblq(month-2);//每步递归都严重依赖上一次递归结果,并占用大量的栈区空间,执行效率极低

    }

    测试上段程序运行时间

    @Test

    public  void test(){

    long startTime = System.currentTimeMillis();

    System.out.println(fblq(50));

    long endTime = System.currentTimeMillis();

    System.out.println("程序运行时间:" + (endTime - startTime) + "ms");    //输出程序运行时间

    }

       程序运行时间:43643ms(非常慢),递归所需栈区空间,以指数级进行增长

    4、尾递归

      如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个函数是尾递归的。尾递归函数的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。

    /**
    * 斐波那契数列尾递归
    */
    public int fblq(int n,int num1,int num2){
    if(n==1){
    return num1;
    }
    return fblq(n-1,num2,num1+num2);
    }

    @Test
    public void Test37(){
    long startTime = System.currentTimeMillis();
    System.out.println(fblq(50,1,1));
    long endTime = System.currentTimeMillis();
    System.out.println("程序运行时间:" + (endTime - startTime) + "ms"); //输出程序运行时间
    }

    程序运行时间:1ms,递归以线性关系增长

    总结:在能使用尾递归时尽量使用尾递归,这样不仅能节省内存资源,而且执行效率更高,但是相比于普通for循环,递归的效率是较低的,所以再不是非递归不可的环境中,尽量使用普通循环代替递归算法。

    希望各位大神,对文中的不足不吝赐教,共同学习,共同进步!!!
  • 相关阅读:
    POJ 1251 Jungle Roads
    1111 Online Map (30 分)
    1122 Hamiltonian Cycle (25 分)
    POJ 2560 Freckles
    1087 All Roads Lead to Rome (30 分)
    1072 Gas Station (30 分)
    1018 Public Bike Management (30 分)
    1030 Travel Plan (30 分)
    22. bootstrap组件#巨幕和旋转图标
    3. Spring配置文件
  • 原文地址:https://www.cnblogs.com/gongli123/p/6925278.html
Copyright © 2011-2022 走看看