递归
递归的定义:
函数内部调用的自身函数的编程技巧称为递归。
构成递归的条件:
- 子问题须与原始问题为同样的事,且更为简单;
- 不能无限制地调用本身,须有个出口,化简为非递归状况处理。
递归的基本原理
- 每一级的函数调用都有自己的变量。
- 每一次函数调用都会有一次返回。当程序执行到某一级递归的结尾处时,它会转移到前一级递归继续执行。程序不能直接返回到main()中的初始调用部分,而是通过递归的每一级逐步返回,即从func()的某一级递归返回到调用它的那一级。
- 递归函数中,位于递归调用前的语句和各级被调函数具有相同的执行顺序。
- 递归函数中,位于递归调用后的语句的执行顺序和各个被调函数的顺序相反。
- 虽然每一级递归都有自己的变量。但是函数代码并不会得到复制。函数代码是一系列的计算机指令。而函数调用就是从头执行相应函数的指令集,除了会每次创建变量,递归调用非常类似于一个循环语句。
- 递归函数中必须包含可以终止递归调用的语句。
递归的优缺点
优点:
- 简洁
- 在树的前序,中序,后序遍历算法中,递归的实现明显要比循环简单得多。
缺点:
效率性: - 递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。
- 递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算,如fibonacci斐波那契数列的递归实现。
性能性: - 调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。
package 递归;
public class numbers {
public static int sum(int i) {
if (i == 1) {
return 1;
} else {
return i + sum(i - 1);
}
}
public static String sums(int i) {
int j = 0;
if (i == 1) {
j = 1;
} else {
j = i + Integer.parseInt(sums(i - 1));
}
return String.valueOf(j);
}
public static String numcheng(int i) {
if (i == 1) {
return "1";
} else {
return (numcheng(i - 1)) + "*" + i;
}
}
public static int mus(int i) {
if (i == 1) {
return 1;
} else {
return</