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

        这两天在学快速排序,在查阅相关资料的时候,发现快速排序的花样实在是多,其中就有一种优化快速排序的方法用到了尾递归,我便又去了解了尾递归,因为接下来的一篇博客中写快速排序决定用上尾递归的方法,所以先记录下关于尾递归的知识。尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量, 直接让被调用的函数返回时越过调用者, 返回到调用者的调用者去,但也并不是必须要在尾部的,换句话说,在递归调用之后还可以有其他的语句执行,只是它们只能在递归调用没有执行时才可以执行。。

    以下是我对尾递归的个人见解: 

        所谓递归就是在调用一个会调用自身的函数,而我们在调用一个函数时,栈内存的操作如下:

    1.系统会将函数中用到的各种参数、返回值等数据压进栈内存中。

    2.然后当调用函数执行完,确认即将返回后,栈内存中的临时数据就会被释放消除。

       函数调用时栈内存的操作如图1所示。

                                                        图1

    那么当一个函数如下:

    
    
    public static int fac(int n)
    {
        if(n ==0 )
        {
            return 1;
        }
        if(n==1)
        {
            return 1;
        }
        else {
            return n*fac(n-1);
        }
    }
    
    

       当上面这个函数被执行时,当程序执行到return (n*func(n-1));时,由于光有一个func(n-1)的返回值还不足以让这个函数返回,它还得乘一个这个函数内的n之后才能返回,所以栈内存就必须留着这个函数内的数据,一直等到func(n-1)的结果出来,然后跟这个函数内的n相乘完了才能确认返回,并释放栈,若是这个递归很深的话,很容易造成栈内存爆炸,如图二。

    图2

       当函数的最后执行代码除了调用函数自身外,不再执行其他运算,编译器会有这样的优化:

       函数在递归调用之前已经把所有的计算任务已经完毕了,他只要把得到的结果全交给子函数就可以了,无需保存什么,子函数其实可以不需要再去创建一个栈帧,直接把就着当前栈帧,把原先的数据覆盖即可。(注意不是所有编译器都有这样的优化。)

       尾递归例子程序如下:

    public static int facTail(int n,int m)
    {
        if(n==0)
        {
            return 1;
        }
        if(n==1)
        {
            return m;
        }
        else 
        {
            
            return facTail(n-1,m*n); 
        }
    }

    先写到这里,大佬们若发现我的理解有不妥之处,欢迎指正。

      

     
  • 相关阅读:
    别让删库这种事情再发生
    别让删库这种事情再发生
    oracle目录结构
    oracle 查看启动时间和运行时间
    oracle 执行计划(连接类型)
    oralce执行计划(三)
    跟踪索引是否有用
    AIX系统之启动
    oracle查看核心进程
    oracle执行计划(二)
  • 原文地址:https://www.cnblogs.com/leo-lv/p/10640666.html
Copyright © 2011-2022 走看看