1.迷宫问题
迷宫问题的情景是这样的,有一个迷宫,其中有墙壁,也就是无法到达的地方,设置一个起点,一个终点,让目标寻找路线,如果找到返回true 否则返回false/**
*
* @param map地图
* @param i 确定坐标
* @param j 确定坐标
* @return 找到了返回true 否则返回false
*/
//map[6][5]是终点
//约定 map[i][j]=0表示没有走 为1表示不能走 为2表示这是一个通路
//需要定义一个寻路策略比如 下->右->上->左
public static boolean setWay(int[][] map,int i,int j) {
if(map[6][5]==2) {//此时通路已经找到
return true;
}else {
if(map[i][j]==0) {//如果当前这个点没走过
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;
}
}else {//此处值可能为1,2,3
return false;
}
}
}
这个算法的核心是setWay函数 传入的i j 参数是目标的初始位置,下面让我来分析一下
首先,第一句话说的是递归出口,当第七行第六列这个位置已经走通了,也就是说明已经抵达终点,此时返回true,每个递归算法都必须要有一个递归出口
当还没到终点时,就要分两种情况,一是当前这个i,j位置还没走过,另一种情况则是走过,是墙,走不通三种情况的合集,故直接返回false即可,重点在于此位置没走的情况。
先给此处赋值2 也就是通路 然后约定一个寻路策略,因为代码是从上到下执行的,所以往上还是往下往左还是往右是需要确定的,本代码是下右上左。这里就要递归了,重点来了!
此时是i,j,在if里调用了i+1,j,也就是把当前位置向下走了一个,这样又会进入一个函数,这个函数中的i比原来大1,然后又会执行各种判断,假如往下走遇到墙了,就会往右找路,这样会有两种情况,一是在调用很多层函数后找到了,这时会返回true,二是没找到,则最上层的栈帧返回false,第二层继续找别的方向,若四个方向都不通,最后就返回false了。
2.八皇后
八皇后的核心函数有两个,一个是判断放的棋子和之前的是否冲突的judge函数,一个是运用递归来放棋子的check函数//放置第n个皇后时 判断当前的是否符合规则 是否和之前的冲突
private boolean judge(int n) {
for(int i=0;i<n;i++) {
//1.两棋子不在一列上 2.两棋子不在一个斜线上
if(array[i]==array[n] || Math.abs(n-i)==Math.abs(array[n]-array[i])) {
return false;
}
}
return true;
}
//编写一个方法放置第n个皇后
private void check(int n) {
if(n==max) {//递归出口:说明已经放完了
show();
return;
}
//依次放入
for(int i=0;i<max;i++) {
//先把当前这个 也就是第n个皇后 放到该行的第1列
array[n] = i;
//判断放置第n个到i列是 是否冲突
if(judge(n)) {
check(n+1);
}
//如果冲突则继续执行 array[n] = i 此时i增加了1
}
}
建立for循环依次放入皇后,最大值是8,i从0到7,首先把当前这个皇后放在当前行的第i个,然后判断是否冲突,如果不冲突就放下一个,如果冲突则继续循环,该皇后放到下一列试试行不行。
3.感想
递归能看懂实际上不是很难,结合jvm对栈帧的理解就能明白每次调用自身的情况,栈中的栈帧是依次从上到下返回的;但是自己写出来就很难,哎。