在过往不知一次的学过递归,每次也能写出,但对其运行的机制以及他的效率都不为之,今天又从新看到递归所以重新学习下,同时也作为我第一篇正式博客的知识。
以下是一个一个最普遍的例子,那个求一个数的阶乘:
public class jiandan_recursion {
static long foo(int i,long sum){
if(i==1)
return 1;
else
return foo2(i,sum);
}
static long foo2(int i,long sum){
if(i==1)
return sum;
else
return foo2(i-1,sum*i);
}
public static void main(String[] args) {
long value=foo(5,1); //该函数是求5的阶乘
System.out.println("该数的阶乘为:"+value);
}
}
该数的阶乘为:120
先开始递归对我来说感觉是一个很神奇的东西,用较少的代码就可以算出你想要的结果,但后来得知递跟非递归相比需要很消耗更多空间和时间,递归需要消耗系统的栈堆,当递归的深度达到一定量是就会造成系统的堆栈溢出。也可得知也会消耗大量的时间。
比如看下个例子:递归和非递归(迭代/循环)时间上的差别
//递归
static long foo(int i){
if(i==1)
return 1;
return foo(i-1)*i;
}
//非递归
static long foo2(int i){
long sum=1;
for(int p=1;p<=i;p++){
sum*=p;
}
return sum;
}
public static void main(String[] args) {
long time1 = System.currentTimeMillis(); //返回当前时间以毫秒为单位
System.out.println("递归调用前的时间 = " + time1);
long i = foo(20);
System.out.println(i);
long time2 = System.currentTimeMillis();
System.out.println("递归调用前的时间 = " + time2);
System.out.println("递归所用的时间 = " + (time2 - time1));
System.out.println("==================================================================");
long time3 = System.currentTimeMillis();
System.out.println("循环调用前的时间 = " + time3);
long i2 = foo2(20);
System.out.println(i2);
long time4 = System.currentTimeMillis();
System.out.println("循环调用前的时间 = " + time4);
System.out.println("循环调用所用的时间 = " + (time4 - time3));
}
递归调用前的时间 = 1552377125450
2432902008176640000
递归调用前的时间 = 1552377125451
递归所用的时间 = 1
==================================================================
循环调用前的时间 = 1552377125451
2432902008176640000
循环调用前的时间 = 1552377125451
循环调用所用的时间 = 0
这个所差的时间可以在运行多次的结果会用一定的差别,但是可以明显的可看当递归的深度达到20次的时候,运算所用的时间用了1-2毫秒,虽然在我们生活中一俩毫秒根本没有感触,但在计算机的世界中便是很长的时间。
所以在尽量能避免使用递归的情况下,就不要使用。
在其他大牛的博客中看到了关于指针优化的问题:尾递归
但是才疏学浅,有点看不懂,所以把这块知识先空着,待我什么参透在来补上。
http://it.deepinmind.com/jvm/2014/04/16/tail-call-optimization-and-java.html
有兴趣的人可以看看,或者在找些别的资料。小弟,先行告退。