Today has been studying tail recursion, read some blog, write down some notes, for later review with
Linear recursion: It is also ordinary recursion, one-way recursion, the last step of a linear recursive function is not a recursive operation, but other operations. When the data volume is very large, it will cause stack overflow, this is because, in each recursive call, the recursive function of the parameters, local variables, etc. to be stored in the stack, if the amount of data is very large, it may overflow.
Tail recursion: It is also a linear iteration, the last step of the tail recursive function is recursion, that is, before the recursion, the whole operation of the first execution, the advantage is that there is no need to spend a lot of stack space to save the last recursive parameters, local variables, and so on, because the last recursive operation after the end of the previous data has been calculated , passed to the current recursive function, so that the local variables and parameters in the last recursion will be deleted, freeing up space, thus not causing stack overflow. However, many compilers do not automatically optimize the function of tail recursion, that is, when the compiler determines that the current operation is recursive operation, it will not care whether it is a linear recursive return is the tail recursion, so will not delete the previous local variables and parameters. In addition, tail recursion can generally be converted into circular statements.
In general, there is little difference in the time complexity of linear recursion and tail recursion (there are, of course, exceptions, such as the Fibonacci sequence, this is because the realization of its linear recursion, resulting in a large number of redundant computations, its time complexity is the point of magnitude, and its implementation of the tail recursion only need linear level of time complexity. However, the spatial complexity of tail recursion is relatively small (this is the premise of the assumption that the tail recursion is optimized), the linear recursion is easy to understand, and the tail recursive performance is better.
Here are two examples:
The two recursive implementations of the factorial of N, the former being linear recursion, the latter being the tail recursion, the latter being in the calculation, the incoming parameter A is 1, that is, the execution Facttsail (n,1), it is obvious that the latter is easily converted into a circular statement.
Two recursive implementations of Fibonacci sequences:
Back to the column page: http://www.bianceng.cnhttp://www.bianceng.cn/Programming/sjjg/
1, linear recursive implementation (this method is very intuitive, very easy to understand, but inefficient, should try to avoid, do not meet the recursive call when the synthetic benefits of the test)
public static int fibonaccirecursively (int n) {
if (n < 2) return
N;
else return
fibonaccirecursively (n-1) + fibonaccirecursively (n-2);
}
2, tail recursive implementation, here need to provide two accumulators: ACC1 and ACC2, call ACC1 assignment 0,ACC2 Assignment 1
Obviously, the method can also be easily converted into circular statements
public static int fibonaccitailrecursively (int n, int acc1, int acc2) {
if (n = 0) return
acc1;
else return
fibonaccitailrecursively (n-1, ACC2, ACC1 + acc2);