zoukankan      html  css  js  c++  java
  • 尾递归

    尾递归的定义

    如果一个函数的所有地柜形式的调用都出现在函数的末尾,我们称这个递归函数是尾递归。当递归调用时整个函数中过最后执行的语句且它的返回值不属于表达式的一部分时,这个地柜调用就是尾递归。尾递归的特点是在回归过程中不用做任何操作,这个特性很重要,因为大多数现代的编译器会利用这种特点自动生成优化的代码。

    尾递归的原理

    当编译器检测到一个函数是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。编译器可以做到这点,因为递归调用时当前活跃期内最后一条待执行的语句,于是这个调用返回时栈帧中并没有其他事情可做,因此也就没有保存栈帧的必要了。通过覆盖当前的栈帧而不是在其之上重新添加一个,这样所使用的栈空间就大大缩减了,这使得实际的运行效率变得更高。

    尾递归的实例

    package com.fpc.Test;
    
    public class TailRescuvie {
        //线性递归
        public int Rescuvie( int n) {
            return ( n == 1 )? 1 : n * Rescuvie(n - 1);
        }
        
        //封装用
        public int tailRescuvie( int n ) {
            return ( n == 0 ) ? 1 : tailRescuive( n , 1 );
        }
        //尾递归
        public int tailRescuive( int n , int a ) {
            return ( n == 1 ) ? a : tailRescuive( n - 1 , a * n);
        }
        
        public static void main( String[] args ) {
            TailRescuvie t = new TailRescuvie();
            System.out.println(t.Rescuvie(5));
            System.out.println(t.tailRescuvie(5));
            
        }
    }

    对于线性递归,他的递归过程如下:

    1. Rescuvie(5)
    2. {5*Rescuvie(4)}
    3. {5*{4*Rescuvie(3)}}
    4. {5*{4*{3*Rescuvie(2)}}}
    5. {5*{4*{3*{2*Rescuvie(1)}}}}
    6. {5*{4*{3*{2*1}}}}
    7. {5*{4*{3*2}}}
    8. {5*{4*6}}
    9. {5*{24}
    10. 120

    对于尾递归,他的递归过程如下:

    1. tailRescuvie(5)
    2. tailRescuvie(5,1)
    3. tailRescuvie(4,5)
    4. tailRescuvie(3,20)
    5. tailRescuvie(2,60)
    6. tailRescuvie(1,120)
    7. 120

    很容易看出,普通的线性递归比尾递归更加消耗资源,在实现上来说,每次重复的过程调用都是的调用链条不断加长,系统不得不使用栈进行数据保存和回复,而尾递归就不存在这样的问题,因为他的状态完全由n和a来保存。

  • 相关阅读:
    栈和队列的存储结构、线性结构和非线性结构
    java 将一个有大量数据的list集合分成指定大小的list集合
    Java和jdbc实现数据库操作的基础例子
    解决连接Oracle 11g报ORA-01034和ORA-27101的错误和报ORA-00119和ORA-00132这个问题
    Java语言类的特性
    Java类与对象
    Java中的字符串(String)
    Java数组
    Java中的流程控制
    Java中的运算符与表达式
  • 原文地址:https://www.cnblogs.com/fangpengchengbupter/p/7985682.html
Copyright © 2011-2022 走看看