递归:程序调用自身的编程技巧称为递归( recursion)
四条基本实现原则
- 基准情形
必须总有某些基准情形,它无需递归就能解除。 - 不断推进
对于那些需要递归求解的情形,每一次递归调用都必须要是求解状况朝基准情形的方向推进 - 设计原则
假设所有的递归调用都能运行。 - 合成效益原则
在求解一个问题的同一实例时,切勿在不同的递归调用中做重复工作
递归算法一般用于解决三类问题:
-
数据的定义是按递归定义的。(Fibonacci函数)
-
问题解法按递归算法实现。
这类问题虽则本身没有明显的递归结构,但用递归求解比迭代求解更简单,如Hanoi问题。 -
数据的结构形式是按递归定义的
如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归地描述。
递归的缺点:
递归算法解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。
迷宫问题
设计一个迷宫,出口。
package recursion.labyrinth;
public class Labyrinth {
public static void main(String[] args) {
//创建一个地图map
int[][] map = new int[10][10];
//数字1代表墙,2代表已经走过的路,3代表不通的路,代表未走的路。
for (int i = 0; i < 10; i++) {
map[i][0] = 1;
map[i][9] = 1;
}
for (int i = 0; i < 10; i++) {
map[0][i] = 1;
map[9][i] = 1;
}
map[1][2]=0;
map[2][2]=1;
map[3][2]=1;
map[3][1]=1;
show(map);
setWay(map,1,1);
System.out.println("--------------------");
show(map);
}
/**
* @param map 地图
* @param i 起点的行数
* @param j 起点的列数
* @return 是否找到路
*/
//定义一个方法找路
public static boolean setWay(int[][] map, int i, int j) {
//到达终点,说明已经找到路。返回结束
if (map[8][8] == 2) {
return true;
} else {
if (map[i][j] == 0) {
//先将此点设置为2,代表走到此处
map[i][j] = 2;
//寻找下一个点
if (setWay(map, i + 1, j)) {
return true;
} else if (setWay(map, i, j + 1)) {
return true;
} else if (setWay(map, i - 1, j)) {
return true;
} else if (setWay(map, i, j - 1)) {
return true;
} else {
//代表此路不通
map[i][j] = 3;
return false;
}
//不是0,为1,2,3则直接返回false
}else {
return false;
}
}
}
//打印迷宫
public static void show(int[][] map){
for (int[] ints : map) {
for (int anInt : ints) {
System.out.print(anInt + " ");
}
System.out.println();
}
}
}