利用尾递归减少栈空间的消耗

利用尾递归减少栈空间的消耗

分类: 算法   482人阅读  评论(3)  收藏  举报
递归 栈 编译器 算法 优化

      首先,需要给出一个定义,什么是尾递归。在《算法精解》中给出的定义如下:

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

      看完上面这段描述,是不是觉得和没说差不多,看不明白。好吧,那就看看下面这张图吧。

利用尾递归减少栈空间的消耗_第1张图片

      这张图的左面是正常的递归,我们可以看到,越往深一层(即函数自身被调用一次),栈就要被多消耗掉一部分空间。而右边这张图,只有两次递归需要用到不同的栈空间,其余都是上次的空间被直接覆盖掉。

      下面,我们利用普通的递归和尾递归计算一个表达式:

       1 + 1/2 + 1/3 + 1/4 + .... + 1/n

      代码如下:

[cpp]  view plain copy print ?
  1. #include <stdio.h>  
  2.   
  3. double pi(double n);  
  4. double pitail(double n, double a);  
  5.   
  6. int main(int argc, char *argv[])  
  7. {  
  8.     printf("%lf\n", pi(5));  
  9.     printf("%lf\n", pitail(5, 0));  
  10.     return 0;  
  11. }  
  12.   
  13. double pi(double n)  
  14. {  
  15.     if (n == 0) {  
  16.         return -1;  
  17.     } else if (n == 1) {  
  18.         return n;  
  19.     } else if (n > 1) {  
  20.         return pi(n-1) + 1/n;  
  21.     }  
  22. }  
  23.   
  24. double pitail(double n, double a)  
  25. {  
  26.     if (n == 0) {  
  27.         return -1;  
  28.     } else if (n == 1) {  
  29.         return a + 1;  
  30.     } else if (n > 1) {  
  31.         return pitail(n-1, a + 1/n);  
  32.     }  
  33. }  

       两种方法得到的结果当然是相同的。

你可能感兴趣的:(算法)