第6章:递归
递归:方法自己调用自己,每次调用时传入不同的变量
1、调用机制
public class Demo01 {
public static void main(String[] args) {
test(4);
}
public static void test(int n){
if (n>2){
test(n-1);
}
System.out.println("n="+n);
}
}
调用规则:
- 当程序执行到一个方法时,就会开辟一个独立的空间(栈)
- 每个空间的数据(局部变量),是独立的。
- 执行一个方法时,就创建一个新的受保护的独立的空间(栈空间)
- 方法的局部变量是独立的,不会相互影响,比如n变量
- 如果方法中使用的是引用类型变量(如数组),就会共享该引用类型的数据
- 递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError
- 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,给方法也就执行完毕。
2、迷宫问题
箭头指示为出口,求最短路径?
设置找路策略:下右上左(也可以设置别的)
0 没走过
1 表示墙
2 表示通路可以
3 走过,走不通
策略:下右上左
public class MiGong {
public static void main(String[] args) {
//二维数组表示迷宫
int[][] map = new int[8][7];
//1表示墙:上下
for (int i = 0; i < 7; i++) {
map[0][i]=1;
map[7][i]=1;
}
//左右
for (int i = 0; i < 8; i++) {
map[i][0]=1;
map[i][6]=1;
}
map[3][1]=1;
map[3][2]=1;
/*
* 0 没走过
* 1 表示墙
* 2 表示通路可以
* 3 走过,走不通
* 下右上左
* */
findWay(map,3,3);
System.out.println("--------------------");
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j]+"\t");
}
System.out.println();
}
}
//(地图,当前位置i,当前位置j)
public static boolean findWay(int[][] map,int i,int j){ //方法返回boolean类型true走得通,false走不通
if (map[6][5]==2){ //出口
return true;
}else{
if (map[i][j]==0){ //初始为0
map[i][j]=2; //走过赋值为2
if (findWay(map,i+1,j)){ //下
return true;
}else if (findWay(map, i, j+1)){ //右
return true;
}else if (findWay(map, i-1, j)){ //上
return true;
}else if (findWay(map, i, j-1)){ //左
return true;
}else {
map[i][j]=3; //走不通赋值为3
return false;
}
}else {
return false;
}
}
}
}
3、八皇后问题
八皇后问题:任意两个皇后都不能处于同一行,同一列或同一斜线上,求有多少种摆法(92)
步骤:
-
第一个皇后先放第一行第一列
-
第二个皇后放在第二行第一列、然后判断是否OK, 如果不OK,继续放在第二列、第三列、依次把所有列都放完,找到一个合适
-
继续第三个皇后,还是第一列、第二列……直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解
-
当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到.
然后回头继续第一个皇后放第二列,后面继续循环执行 1,2,3,4的步骤
使用一维数组即可:如arr[8] = {0 , 4, 7, 5, 2, 6, 1, 3}
其中4 表示第二个皇后,放在第五列(从0开始)
斜率的计算:
斜率=(3-1)/(1-0),当斜率为1或-1时两点在同一对角线上
public class Queue8 {
int max=8; //几个皇后 4表示第二个皇后(n=1),摆放在第2行(i=1)第5列
int[] array= new int[max]; //例:arr = {0 , 4, 7, 5, 2, 6, 1, 3}
int count=0; //有多少种解法
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
queue8.check(0);
}
//n第几个皇后
private void check(int n){
if (n==max){
print();
return;
}
for (int i = 0; i < max; i++) {
array[n]=i;
if (judge(n)){
check(n+1);
}
}
}
/**
* 判断第n个皇后和之前的皇后摆放是否冲突
* @param n 第几个皇后
* @return true不冲突 false冲突
*/
public boolean judge(int n){
for (int i = 0; i < n; i++) {
//在同一列 在同一斜线
if (array[i]==array[n]||Math.abs(n-i)==Math.abs(array[n]-array[i])){
return false;
}
}
return true;
}
//打印皇后摆放位置解法
public void print(){
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
System.out.println();
}
}