尾递归就是只有递推没有回归的递归.
我用java程序分别以迭代、递归、尾递归的方式实现斐波那契数列(45),然后观察他们的运行所花费的时间。
public class Test {
public int iterator(int n) {
if(n <= 0) {
return 0;
}
int first = 1;
int second = 1;
int result = 1;
for(int i = 3; i <= n; ++i) {
result = first + second;
first = second;
second = result;
}
return result;
}
public int recursion(int n) {
if(n <= 0) {
return 0;
}
if(n <= 2) {
return 1;
}
return recursion(n - 1) + recursion(n - 2);
}
public int tailRecursion(int n, int first, int second) {
if(n <= 0) {
return 0;
}
if(n <= 2) {
return second;
}
return tailRecursion(n - 1, second, first + second);
}
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
Test test = new Test();
//System.out.println(test.iterator(n));
//System.out.println(test.recursion(n));
System.out.println(test.tailRecursion(n, 1, 1));
}
}
迭代:0.054s
递归:3.615s
尾递归:0.057s
迭代竟然和非递归的时间相差无几,以前一直看书上说迭代效率低,但是不知低在哪,现在终于知道了,递推的时候需要压栈,栈维护了每个函数调用的信息直到回归的时候才释放(出栈)。而尾递归因为没有回归过程,不需要维护一个庞大的栈,新调用的函数会把原先的函数覆盖掉。
然后我又用c语言实现了一遍,结果令我震惊。
#include <stdio.h>
int iterator(int n) {
if(n <= 0) {
return 0;
}
int first = 1;
int second = 1;
int result = 1;
int i = 0;
for(i = 3; i <= n; ++i) {
result = first + second;
first = second;
second = result;
}
return result;
}
int recursion(int n) {
if(n <= 0) {
return 0;
}
if(n <= 2) {
return 1;
}
return recursion(n - 1) + recursion(n - 2);
}
int tailRecursion(int n, int first, int second) {
if(n <= 0) {
return 0;
}
if(n <= 2) {
return second;
}
return tailRecursion(n - 1, second, first + second);
}
int main() {
//printf("%d\n", iterator(45));
//printf("%d\n", recursion(45));
printf("%d\n", tailRecursion(45, 1, 1));
return 0;
}
迭代:0.001s
递归:7.307s
尾递归:0.001s
c语言的递归竟然是java的两倍,看来c比java快的结论太过武断,要具体情况具体分析。