定义:
大家都用过递归,就是函数自己调用自己。尾递归是一种编程技巧,如果一个函数中所有递归形式的调用都出现在函数的末尾,且递归调用是整个函数体中最后执行的语句且它的返回值不属于表达式的一部分时,这个递归就是尾递归。
原理:
尾递归在函数式编程语言比较常见,编译器能够将其优化成普通循环。 尾递归和递归最大的不同就是在内存占用上,普通递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,而后计算收缩,因此递归次数过多容易造成栈溢出;而尾递归只会占用恒量的内存。但是Python,Java,Pascal,C#等语言编译器无法实现尾递归的优化,还是用循环解决吧。
实例:
计算斐波那契数列第n项,如下用递归、尾递归、循环三种方式实现。
#include "stdio.h"
int fibonacci(int n);
int fibonacci_tail(int n, int $ret1, int $ret2);
int fibonacci_cycle(int n);
int main(void)
{
int rs,rs2,rs3,n;
n=10;
rs = fibonacci(n);
rs2 = fibonacci_tail(n, 0, 1);
rs3 = fibonacci_cycle(n);
printf("%d\n", rs);
printf("%d\n", rs2);
printf("%d\n", rs2);
return 0;
}
//计算斐波那契数列第n项
//0、1、1、2、3、5、8、13、21、34、……
int fibonacci(int n)
{
if (n == 0) return 0;
else if (n == 1) return 1;
else return fibonacci(n-1)+fibonacci(n-2);
}
int fibonacci_tail(int n, int ret1, int ret2)
{
//printf("factorial_tail(%d, %d, %d) \n",n-1,ret1,ret1+ret2);
if (n == 0) return ret1;
else return fibonacci_tail(n-1, ret2, ret1 + ret2);
}
int fibonacci_cycle(int n)
{
int fib;
int f0 = 0;
int f1 = 1;
if (n == 0) return f0;
else if (n == 1) return f1;
else {
for (int $i = 2; $i <= n; $i++) {
fib = f0 + f1;
f0 = f1;
f1 = fib;
}
return fib;
}
}