[java]-算法与数据结构-第六章-递归

六、递归

1. 概念

递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁、
递归–百度百科

2. 递归调用机制

1)打印问题

    public static void test1(int n){
    
    
        if(n > 0){
    
    
            test1(--n);
        }
        System.out.println(n);
        return;
    }

2)阶乘问题

    public static int test2(int n) {
    
    
        if (n == 1) {
    
    
            return 1;
        } else {
    
    
            return test2(n - 1) * n; // 1 * 2 * 3
        }
    }

3. 递归需要遵守的重要规则

递归需要遵守的重要规则:

  1. 执行一个方法时, 就创建一个新的受保护的独立空间(栈空间)
  2. 方法的局部变量是独立的, 不会相互影响, 比如 n 变量
  3. 如果方法中使用的是引用类型变量(比如数组), 就会共享该引用类型的数据.
  4. 递归必须向退出递归的条件逼近, 否则就是无限递归,出现 StackOverflowError
  5. 当一个方法执行完毕, 或者遇到 return, 就会返回, 遵守谁调用, 就将结果返回给谁, 同时当方法执行完毕或者返回时, 该方法也就执行完毕

4. 迷宫问题

在这里插入图片描述

递归需要遵守的重要规则
递归需要遵守的重要规则:

执行一个方法时, 就创建一个新的受保护的独立空间(栈空间)
方法的局部变量是独立的, 不会相互影响, 比如 n 变量
如果方法中使用的是引用类型变量(比如数组), 就会共享该引用类型的数据.
递归必须向退出递归的条件逼近, 否则就是无限递归,出现 StackOverflowError
当一个方法执行完毕, 或者遇到 return, 就会返回, 遵守谁调用, 就将结果返回给谁, 同时当方法执行完毕或者返回时, 该方法也就执行完毕

1)代码

public class Test02_迷宫 {
    
    

    public static void main(String[] args) {
    
    
        // 1. 创建二维数组模拟迷宫
        int[][] map = new int[8][7];
        // 2. 1表示墙
        for (int i = 0; i < map.length; i++) {
    
    
            for (int j = 0; j < map[i].length; j++) {
    
    
                if (i == 0 || i == 7) {
    
    
                    map[i][j] = 1;
                } else {
    
    
                    map[i][0] = 1;
                    map[i][6] = 1;
                }
            }
        }
        // 设置挡板
        map[3][1] = 1;
        map[3][2] = 1;

        for (int[] ints : map) {
    
    
            System.out.println(Arrays.toString(ints));
        }
        boolean b = setWay2(map, 1, 1);
        System.out.println("-------迷宫走完--------");
        for (int[] ints : map) {
    
    
            System.out.println(Arrays.toString(ints));
        }
    }

    // 使用递归给小球找路
    /*
     1. map 表示地图
     2. i,j 表示从地图的哪个位置开始触发
     3. 如果小球能到 map[6][5],说明小球出来了
     4. 约定:
        - 当map[i][j]为0,表示该点没有走过,当为 1表示墙,为2表示是通道. 3 表示已经探测过了但是,此路不通Z下
     5. 走迷哦给你个,确定一个策略 下 -》 右 -》 上 -》 左


    */
    public static boolean setWay(int[][] map, int i, int j) {
    
    
        if (map[6][5] == 2) {
    
    
            return true;
        } else {
    
    
            if (map[i][j] == 0) {
    
    
                // 当前节点还没有走过s
                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 {
    
    
                // map[i][j] != 0,可能是 1,2,3
                return false;
            }

        }
    }

    // 修改找路的策略,改成 上 -> 右 -> 下 -> 左
     public static boolean setWay2(int[][] map, int i, int j) {
    
    
        if (map[6][5] == 2) {
    
    
            return true;
        } else {
    
    
            if (map[i][j] == 0) {
    
    
                // 当前节点还没有走过s
                map[i][j] = 2;// 假设该点是可以走通的
                if (setWay2(map, i - 1, j)) {
    
    
                    // 向上走,
                    return true;
                } else if (setWay2(map, i, j+1)) {
    
    
                    // 向右走
                    return true;
                } else if (setWay2(map, i + 1, j)) {
    
    
                    // 向下走
                    return true;
                } else if (setWay2(map, i, j-1 )) {
    
    
                    // 向左走
                    return true;
                } else {
    
    
                    // 说明该点走不通
                    map[i][j] = 3;
                    return false;
                }
            } else {
    
    
                // map[i][j] != 0,可能是 1,2,3
                return false;
            }

        }
    }

    // 求出最短路径
}

5. 八皇后问题(回溯算法)

1)思路分析

  1. 第一个皇后先放第一行第一列
  2. 第二个皇后放在第二行第一列、 然后判断是否 OK, 如果不 OK, 继续放在第二列、 第三列、 依次把所有列都放完, 找到一个合适
  3. 继续第三个皇后, 还是第一列、 第二列……直到第 8 个皇后也能放在一个不冲突的位置, 算是找到了一个正确解
  4. 当得到一个正确解时, 在栈回退到上一个栈时, 就会开始回溯, 即将第一个皇后, 放到第一列的所有正确解,全部得到. 5. 然后回头继续第一个皇后放第二列, 后面继续循环执行 1,2,3,4 的步骤

说明:使用一维数组构建棋盘,arr[8]={0,4,7,5,2,6,1,3}

  arr[i] = val;  val = 第 i+1 个皇后

2)代码

public class Test03_八皇后问题 {
    
    

    // 1. 定义一个 map 表示共有多少个皇后
    static int max = 8;
    // 2. 定义数组,皇后防止位置
    static int[] array = new int[max];

    // 3. 打印次数
    static int count = 0;
    public static void main(String[] args) {
    
    

        check(0);
        System.out.println(count);
//        print();

    }

    // 防止第 n 个皇后
    private static void check(int n){
    
    
        if(n == max){
    
    
            // 放到 第 8 个皇后,结束
            print();
            count++;
            return;
        }
        // 循环依次放入皇后,并且判断是否冲突
        for (int i = 0; i < max; i++) {
    
    
            // 1. 先把当前皇后n,放到改该行的第1列,
            array[n] = i;
            // 2. 放皇后放到 i列时,是否冲突
            if(judge(n)){
    
    
                // 3. 接着放 n+1 皇后,
                check(n+1);
            }
            // 3. 冲突 当前皇后向右移动。
        }
    }

    // 当我们防止第 n 个皇后时,检测该皇后是否和前面已经摆放的皇后是否冲突.
    private static boolean judge(int n){
    
    
        // n 表示 第 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;
    }

    // 写一个方法,可以将最后结果
    private static void print(){
    
    
        System.out.println(Arrays.toString(array));
    }
}

猜你喜欢

转载自blog.csdn.net/m0_56186460/article/details/124225161