根据尚硅谷的韩顺平老师的数据结构视频总结的笔记
观看视频的网址
看个实际应用场景,迷宫问题(回溯), 递归(Recursion)
简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
1、打印问题
2、阶乘问题
package recursion; /** * @description: 阶乘解决的俩个问题 * @auther:田坤 * @date 2020/10/7 15:40 **/ public class RecursionTest { public static void main(String[] args) { test(5); int i = jieCheng(5); System.out.println("阶乘为:"+i); } //打印问题 public static void test(int num){ if(num > 2){ test(num-1); } System.out.println(num); } //阶乘问题 public static int jieCheng(int num){ if(num == 1) return 1; else { return jieCheng(num - 1) * num; } } }
代码实现
package recursion; /** * @description: 利用递归来解决迷宫问题 * @auther:田坤 * @date 2020/10/7 15:59 **/ public class MiGong { public static void main(String[] args) { //利用数组生成一个迷宫地图 int[][] map = new int[8][7]; //生成墙 for (int i = 0; i < 7; i++) { map[i][0] = 1; map[i][6] = 1; map[0][i] = 1; map[7][i] = 1; } //生成挡板 map[3][1] = 1; map[3][2] = 1; //遍历地图 for (int i = 0; i < map.length; i++) { int[] temp = map[i]; for (int j = 0; j <temp.length ; j++) { System.out.print(map[i][j]+" "); } System.out.println(); } //使用递归回溯给小球找路 setWay(map,1,1); System.out.println("小球找路的路径"); for (int i = 0; i < map.length; i++) { int[] temp = map[i]; for (int j = 0; j <temp.length ; j++) { System.out.print(map[i][j]+" "); } System.out.println(); } } /** * 如果小球到 map[6][5]则说明通路找得到 * 约定:当 map[i][j]为0则表示该点没有走过, 为1 则表示强, 为2则表示通路可以走, 为3则表示已经走过但走不通 * 在走迷宫时,我们需要设定一个策略(方法)小球如何走: 下-》右-》上-》左 * * @param map 地图 * @param i 小球开始位置的横坐标 * @param j 小球开始位置的纵坐标 * @return 在某点的路是否能通行,能 true 不能则 false; */ 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; } } } }
2、八皇后问题算法的解题思路
第一个皇后先放第一行第一列第二个皇后放在第二行第一列、然后判断是否OK, 如果不OK,继续放在第二列、第三列、依次把所有都放完,找到一个合适继续第三个皇后,还是第一列、第二列……直到第8个皇后也能放在一个不冲突的位置,算是找到了一个正确解当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到.然后回头继续第一个皇后放第二列,后面继续循环执行 1,2,3,4的步骤
说明:
理论上应该创建一个二维数组来表示棋盘,但是实际上可以通过算法,用一个一位数组即可解决问题,arr[8] = {0,4,7,5,2,6,1,3},对应arr下标 表示第几行,即第几个皇后,arr[i] = val, val 表示第i+1个皇后,放在第 i+1行的第val + 1列。
3、八皇后问题算法代码实现:
package recursion; /** * @description: 利用递归回溯解决八皇后问题 * @auther:田坤 * @date 2020/10/7 17:47 **/ public class Queen8 { private int max = 8; //皇后的个数 private int[] arr = new int[max]; ; //每个皇后所存在的位置 private int count = 0; //符合的个数 private int conflictCount = 0; //判断冲突的次数 public static void main(String[] args) { Queen8 queen8 = new Queen8(); queen8.check(0); System.out.println("解法的个数为:"+queen8.count); System.out.println("判断冲突的的次数为:"+queen8.conflictCount); } //放置第n个皇后 public void check(int num){ if(num == max){ //第八个皇后放好,则表示成功 count++; print(); return; } //依次放入皇后,并判断是否冲突 for (int i = 0; i < max; i++) { //先把当前的皇后num 放再第一列 arr[num] = i; //判断第num个皇后到i列时,是否冲突 if(conflict(num)) check(num+1); } //如果冲突就继续执行 arr[n] = i ;即 第n个皇后放置在本行的后移一个位置 } /** * 解决第n个皇后于前面皇后的冲突问题 * @param n 第几个皇后 * @return 当前第n个皇后是否和前面皇后的位置冲突 */ public boolean conflict(int n){ conflictCount++; //随意两个皇后不能再同一列,且不能再同一斜线上 for (int i = 0; i < n; i++) { /** * arr[n] == arr[i] 表示当前第n个皇后于前面第i个皇后在同一列 * Math.abs(n-i) == Math.abs(arr[n] - arr[i]) 表示当前第n个皇后于前面第i个皇后在同一斜线上 * * 不用判断是否在一行,n每次都在递增 */ if(arr[n] == arr[i] || Math.abs(n-i) == Math.abs(arr[n]-arr[i])){ return false; } } return true; } //打印皇后的位置 public void print(){ for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+" "); } System.out.println(); } }