尾递归

今天没事到公司,老毛病又犯了,到网上搜索一堆电子书来翻翻。

看到尾递归的概念,发现自己之前都没注意。

wiki上的说明:

计算机科学里,尾调用是指一个函数里的最后一个动作是一个函数调用的情形:即这个调用的返回值直接被当前函数返回的情形。这种情形下称该调用位置为尾位置。若这个函数在尾位置调用本身(或是一个尾调用本身的其他函数等等),则称这种情况为尾递归,是递归的一种特殊情形。尾调用不一定是递归调用,但是尾递归特别有用,也比较容易实现。

尾调用的重要性在于它可以不在调用栈上面添加一个新的堆栈帧——而是更新它,如同迭代一般。尾递归因而具有两个特征:

  • 调用自身函数(Self-called);
  • 计算仅占用常量栈空间(Stack Space)。

而形式上只要是最后一个return语句返回的是一个完整函数,它就是尾递归

尾递归在回归的过程中不用做任何操作,大多数的现在编译器会利用这种特点自动生成优化的代码,计算过程中,仅需要占用常量的堆栈空间(覆盖调用堆栈而不是创建新的)。

 

以计算阶乘为例,普通递归调用如下:

int fact(int n) {
    if (n < 0)
        return 0;
    else if (n == 0 || n == 1)
        return 1;
    else
        return n * fact(n - 1);
}

由于最后一个步骤进行的是乘法的计算,不仅仅调用fact()函数,因此不是尾递归。

 

阶乘的计算过程可以表示为:

F(n, a) = |a                      如果 n=0, n=1

              |F(n-1, na)         如果 n>1

本质上,利用na迭代。

尾递归代码可以写为:

int facttail(int n, int a) {
    if (n < 0)
        return 0;
    else if (n == 0)
        return 1;
    else if (n == 1)
        return a;
    else
        return facttail(n - 1, n * a);
}

 

 

posted @ 2014-03-22 16:12  matteoxie  阅读(380)  评论(0)    收藏  举报