waitwolf 2019-12-30
递归
1.递归的概念
递归就是自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时可以让代码变得简洁
2.递归需要遵守的重要规则
1)执行一个方法时,就创建一个新的受保护的独立空间(栈空间) 2)方法的局部变量是独立的,不会相互影响 3)如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据 4)递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError 5)当一个方法执行完毕,或者遇到return,就会返回。遵守谁调用就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕
3.迷宫问题
思路:
map表示地图,i,j表示从地图的那个位置出发(i,j) 如果球能到map[6][5]位置,说明找到出口 约定:map[i][j]为0表示此路还没有走过,2表示道路走过了是通的,3表示道路走过了但是没走通 在走迷宫时,需要确定一个策略:下->右->上->左,如果走不通,就回溯
具体代码
package com.ujiuye.recursion;
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 < 7;i++) {
map[i][0] = 1;
map[i][6] = 1;
}
//设置两个挡板
map[3][1] = 1;
map[3][2] = 1;
System.out.println("迷宫的情况");
for(int i = 0;i < 8;i++) {
for(int j = 0;j < 7;j++) {
System.out.print(map[i][j] +" ");
}
System.out.println();
}
setWay(map, 1, 1);
System.out.println("小球走过,并标识的迷宫情况");
for(int i = 0;i < 8;i++) {
for(int j = 0;j < 7;j++) {
System.out.print(map[i][j] +" ");
}
System.out.println();
}
}
public static boolean setWay(int[][] map,int i,int j) {
//如果map[6][5]已经走了并且能走通,表示出了迷宫
if(map[6][5] == 2) {
return true;
}else {
//如果没有出迷宫,需要看哪条路能走
//1 如果为0,表示没有走过,需要尝试走一遍
if(map[i][j] == 0) {
//先把路设置为已经走过的,2或3都代表走过,假如能走通
//如果走不通,最后再更改这条线的值为3
map[i][j] = 2;
//按照下右上左的顺序走
//1下,i+1,递归调用看这条线是否能走通
if(setWay(map,i+1,j)) {
return true;
//2右,j+1,递归调用看这条线是否能走通
}else if(setWay(map,i,j+1)) {
return true;
//3上,i-1,递归调用看这条线是否能走通
}else if(setWay(map,i-1,j)) {
return true;
//4左,j-1,递归调用看这条线是否能走通
}else if(setWay(map,i,j-1)) {
return true;
}else {
//下右上左都没有走通
map[i][j] = 3;
return false;
}
//表示这条路走过了,1或2或3,走过的路就不再走了
}else {
return false;
}
}
}
}4.八皇后问题
思路;
1)第一个皇后先放第一行第一列 2)第二个皇后放在第二行第一列,然后判断是否ok,如果不OK,继续放在第二列,第三列。。。依次把所有列都放完,找到一个合适的位置 3)。。。 4)当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后放到第一列的所有正确解全部得到 5)然后继续吧第一个皇后放在第二列,继续循环
具体代码
package com.ujiuye.recursion;
public class Queue8 {
//定义有几个皇后
int max = 8;
static int count = 0;
//定义一个一维数组,行数没有显示,数组显示的是列数
//arr[i] i 表示第i+1个皇后,arr[i]表示在arr[i]+1列
int[] array = new int[max];
public static void main(String[] args) {
Queue8 queue8 = new Queue8();
//从第一个皇后开始放置
queue8.check(0);
System.out.printf("总共有%d种放置方式",count);
}
//写一个方法放置第n个皇后
private void check(int n) {
//n最大值为7,如果等于8说明全部摆放完毕
if(n == max) {
print();
return;
}
//依次放入皇后,判断是否冲突,i表示第i+1列
for(int i = 0;i < max;i++) {
//第n+1个皇后放在第一列
array[n] = i;
//判断放置第n+1个皇后到第i+1列时,是否冲突
if(judge(n)) {
//如果不冲突,放下一个皇后
check(n+1);
}
//如果冲突,就把该皇后放的位置的列数加1,即for循环
}
}
//查看当放置第n个皇后,判断位置是否冲突
//每个皇后在一行,所以判断列的位置有没有直线或者斜线
private boolean judge(int n) {
//加入第四个皇后,n=3,就要跟前三个比较,次数就是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;
}
//输出皇后摆放的位置array={0,4,7,5,2,6,1,3}
//h1:1,h2:5,h3:8,h4:6,h5:3,h6:7,h7:2,h8:4
private void print() {
count++;
for(int i = 0;i < array.length;i++) {
System.out.print(array[i]+"");
}
System.out.println();
}
}。