相信对it从业人员来说,递归这个概念再熟悉不过了,说白了就是一个自己调用自己的函数,每个递归函数必须得有个终止条件, 要不然就会发生无限递归了, 永远都出不来了。
比如计算阶乘的函数
public double factorial(int num){ if(n==1){ return 1; }else{ return n*factorial(n-1); } }
里面的计算实际是:
fastortial(4)=4*fastortial(3)
fastortial(3)=4*3*fastortial(2)
fastortial(2)=4*3*2*fastortial(1)
fastortial(1)=4*3*2*1
再一层层的往上返回;
同样是计算阶层的函数,若添加一个参数:
public double fastortial(int num, double result){ if(num==1){ return 1; }else{ return fastortial(n-1, n*result) } }
计算过程:
fastortial(4) = fastortial(3, 4*fastortial(2,3*fastortial(1,fastortial(2))));
避免了还要一层层往上面返回的问题;
计算机发现这种情况, 只用一个栈帧就可以搞定这些计算, 无论你的n 有多大。
这种方式就是我们常说的尾递归了, 当递归调用是函数体中最后执行的语句并且它的返回值不属于表达式一部分时, 这个递归就是尾递归。
现代的编译器就会发现这个特点, 生成优化的代码, 复用栈帧。 第一个算法中因为有个n * factorial(n-1) , 虽然也是递归, 但是递归的结果处于一个表达式中, 还要做计算, 所以就没法复用栈帧了, 只能一层一层的调用下去。 ”