数据结构--递归
1.递归应用场景
实际应用场景,迷宫问题(回溯)、八皇后问题、快速排序、 递归(Recursion)
2.递归的概念
3.递归需要遵守的重要规则
1) 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
2) 方法的局部变量是独立的,不会相互影响, 比如 n 变量
3) 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.
4) 递归必须向退出递归的条件逼近,否则就是无限递归,出现 StackOverflowError,死归了:)
5) 当一个方法执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕
4. 递归-迷宫问题
1 package mainProject; 2 //1:代表墙 2:代表可通行路径 3:代表阻塞路径 3 4 //迷宫算法 5 public class MiGongDemo { 6 public static void main(String[] args) { 7 int[][] map = new int[8][7]; 8 getMap(map); 9 setWay(map,1,1); 10 System.out.println("——————————————————————————————————"); 11 getMap(map); 12 } 13 14 //地图绘制 15 public static void getMap(int[][] map){ 16 17 18 for(int i=0;i<7;i++){ 19 map[0][i] = 1; 20 map[7][i] = 1; 21 } 22 for(int i=0;i<8;i++){ 23 map[i][0] = 1; 24 map[i][6] = 1; 25 } 26 map[3][1] = 1; 27 map[3][2] = 1; 28 map[4][3] = 1; 29 for(int i =0;i<8;i++){ 30 for(int j = 0;j<7;j++){ 31 System.out.print(map[i][j]+" "); 32 } 33 System.out.println(); 34 } 35 } 36 /** 37 * 寻路方法 38 * @param map:地图 39 * @param i:位置i坐标 40 * @param j:位置j坐标 41 * 执行策略:上右上左 42 */ 43 public static boolean setWay(int[][] map,int i,int j){ 44 if(map[6][5] == 2){ 45 //找到目标位置了 46 return true; 47 }else { 48 if(map[i][j] == 0){ 49 map[i][j] = 2; 50 if(setWay(map,i+1,j)){ 51 return true; 52 }else if(setWay(map,i,j+1)){ 53 return true; 54 }else if(setWay(map,i-1,j)){ 55 return true; 56 }else if(setWay(map,i,j-1)){ 57 return true; 58 }else { 59 map[i][j] = 3; 60 return false; 61 } 62 }else { 63 return false; 64 } 65 } 66 } 67 68 }
结果
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 0 0 0 1
1 0 0 1 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
——————————————————————————————————
1 1 1 1 1 1 1
1 2 0 0 0 0 1
1 2 2 2 0 0 1
1 1 1 2 2 0 1
1 0 0 1 2 0 1
1 0 0 0 2 0 1
1 0 0 0 2 2 1
1 1 1 1 1 1 1
1) 第一个皇后先放第一行第一列
2) 第二个皇后放在第二行第一列、然后判断是否 OK, 如果不 OK,继续放在第二列、第三列、依次把所有列都放完,找到一个合适
3) 继续第三个皇后,还是第一列、第二列……直到第 8 个皇后也能放在一个不冲突的位置,算是找到了一个正确解
4) 当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解, 全部得到.
5) 然后回头继续第一个皇后放第二列,后面继续循环执行 1,2,3,4 的步骤
1 package mainProject; 2 3 4 //八皇后问题 5 public class QueueDemo { 6 //八个皇后 表示共有多少个皇后 7 private static int maxSize = 4; 8 //定义数组 array, 保存皇后放置位置的结果,比如 arr = {0 , 4, 7, 5, 2, 6, 1, 3} 9 //下标1 value0:第一行 第1个位置;下标2 value4:第二行 第5个位置 10 private static int[] array = new int[maxSize]; 11 private static int count = 0; 12 13 public static void main(String[] args) { 14 check(0); 15 System.out.println(count); 16 } 17 18 19 //打印输出结果 20 public static void printQueue(){ 21 count++; 22 for(int i = 0;i<array.length;i++){ 23 System.out.print(array[i]+" "); 24 } 25 System.out.println(); 26 } 27 28 /** 29 * //判断前后皇后是否冲突 30 * @param n :第n个皇后 31 */ 32 public static boolean judge(int n){ 33 for(int i = 0;i<n;i++){ 34 //1. array[i] == array[n] 表示判断 第 n 个皇后是否和前面的 n-1 个皇后在同一列(array【x】 ==>表示位置,i/n表示第几个皇后) 35 //2. Math.abs(n-i) == Math.abs(array[n] - array[i]) 表示判断第 n 个皇后是否和第 i 皇后是否在同一斜线 36 if(array[i]==array[n] || Math.abs(n-i) == Math.abs(array[n]-array[i])){ 37 return false; 38 } 39 } 40 return true; 41 } 42 43 //放置第n个皇后 44 //特别注意: check 是 每一次递归时,进入到 check 中都有 for(int i = 0; i < max; i++),因此会有回溯 45 public static void check(int n){ 46 //如果皇后数等于最大拟定数,那么完成放置 47 if(n == maxSize){ 48 printQueue(); 49 return; 50 } 51 //依次放入皇后,并判断是否冲突 52 for(int i = 0;i < maxSize;i++){ 53 //先把当前这个皇后 n 的位置, 放到该行的第 i 列 54 //array【x】 ==>表示位置 55 array[n] = i; 56 if(judge(n)){ 57 //不冲突 接着放 n+1 个皇后,即开始递归 58 check(n+1); 59 } 60 //如果冲突,就继续执行 array[n] = i; 即将第 n 个皇后,放置在本行得 后移的一个位置 61 } 62 } 63 }