学习数据结构笔记(5)=====>递归

学习数据结构笔记(5)=====>递归,第1张

学习数据结构笔记(5)=====>递归

学习来源–>传送门–>尚硅谷Java数据结构与java算法(Java数据结构与算法)


推荐这位大佬的文章 ;掌握递归—>什么是递归,通过这篇文章,让你彻底搞懂递归

ml
    • 1.递归的简易案例
    • 2.迷宫问题
    • 3.八皇后问题


1.递归的简易案例

递归,在方法自身内调用自己,但是传递参数不同; 调用后一直到最后,然后再一步步地把获得的结果返回到调用的位置.

public class Demo {
    public static void main(String[] args) {
       getNum(5);
    }
    
    //简易递归案例;
    public  static void getNum(int n){
        if(n > 2){
            getNum(n - 1);
        }
        System.out.println("n-->"+ n);
    }
}

得到结果

n-->2
n-->3
n-->4
n-->5

模拟过程图解

具体的调用过程;

  • main() , getNum(5)
  • 此时 n=5; getNum(5) 条件判断后–> getNum(4);
  • 此时 n=4; getNum(4) 条件判断后–> getNum(3);
  • 此时 n=3; getNum(3) 条件判断后–> getNum(2);
  • 此时 n=2; getNum(2) 条件判断–> sout输出 n=2;
  • 返回; sout 输出 n=3;
  • 返回; sout 输出 n=4;
  • 返回; sout 输出 n=5;
  • 最终结果 2 ; 3; 4; 5;

但是,若给执行条件外加一层else{};那么执行的结果就只有一个

public class Demo {
    public static void main(String[] args) {
        getNum2(5);
    }
    
    //简易递归案例2;
    public  static void getNum2(int n){
        if(n > 2){
            getNum2(n - 1);
        }
        //若在其中加入else语句;
        else {
            System.out.println("n-->"+ n);
        }
    }
}

执行结果

n-->2

过程模拟图解;
当调用的结果返回时,发现符合 (n>2) 的条件,他也就不会再去走另一条路了

若加入else语句; 在返回时,由于不符合条件,不再执行sout输出

  • main() , getNum(5)
  • 此时 n=5; getNum(5) 条件判断后–> getNum(4);
  • 此时 n=4; getNum(4) 条件判断后–> getNum(3);
  • 此时 n=3; getNum(3) 条件判断后–> getNum(2);
  • 此时 n=2; getNum(2) 条件判断–> sout输出 n=2;
  • 返回;
  • 返回;
  • 返回;
  • 最终结果 2 ;

阶乘的案例;

public class Demo {
    public static void main(String[] args) {
        //阶乘调用;
        int i = factorial(5);
        //System.out.println(i);
    }

    //阶乘递归;
    public static int factorial(int num){
        return num == 1 ? 1 :num*factorial(num-1);
    }
}    

图解就不做图了;
具体过程为–>

  • main() ; factorial(5);
  • num =5; factorial(5) --> 5 * factorial(4)
  • num =4; factorial(4) --> 4 * factorial(3)
  • num =3; factorial(3) --> 3 * factorial(2)
  • num =2; factorial(2) --> 2 * factorial(1)
  • num =1; factorial(1) --> 得到 1 接着向上执行;
  • num =2; 2*factorial(1)–> 得到 2 接着向上执行;
  • num =3; 3*factorial(2)–> 得到 6 接着向上执行;
  • num =4; 4*factorial(3)–> 得到 24 接着向上执行;
  • num =5; 5*factorial(4)–> 得到 120 得到最终结果为 120;
2.迷宫问题

有一个小球要从黑色的位置到达对角处

0 -> 表示没走的点位; 1 ->表示围墙(不能通过); 2 ->表示走过的可行点; 3 ->表示走过的不可行点;

这就需要用到回朔法;小球在向前探索的过程中,遇到围墙就需要改变方向;
下面这种是以 下->右 ->上 -> 左的方向 前进的;

public class MazeDemo {
    public static void main(String[] args) {

        //定义二维数组作为迷宫;
        int[][] mazeArray = new int[8][7];
        //规定:  0 -> 表示没走的点;  1 ->表示围墙; 2 ->表示走过的可行点; 3 ->表示走过的不可行点;
        //先初始化构造迷宫; 上下左右用围墙; 以及中间几个特殊点作为围墙;
        for (int i = 0; i < 7; i++) {
            mazeArray[0][i] = 1;
            mazeArray[7][i] = 1;
        }
        for (int i = 0; i < 8; i++) {
            mazeArray[i][0] = 1;
            mazeArray[i][6] = 1;
        }
        //其他点的围墙
        mazeArray[2][1] = 1;
        mazeArray[2][2] = 1;
        mazeArray[3][1] = 1;
        mazeArray[3][2] = 1;
        mazeArray[3][3] = 1;
        mazeArray[3][4] = 1;

        //输出查看原迷宫;
        System.out.println("通行前的迷宫===>");
        for (int[] ints : mazeArray) {
            for (int i : ints) {
                System.out.print(i + "t");
            }
            System.out.println();
        }

        //调用方法1,执行;
        System.out.println(getSWay1(mazeArray, 1, 1));
        System.out.println("下右上左==>通行后的迷宫===>");
        for (int[] ints : mazeArray) {
            for (int i : ints) {
                System.out.print(i + "t");
            }
            System.out.println();
        }
    }

    
    public static boolean getSWay1(int[][] mazeArray, int i, int j) {
        //定义结束点;
        if (mazeArray[6][5] == 2) {
            return true;
        }
        //若点位为0,即初始点;
        if (mazeArray[i][j] == 0) {
            //假设取到的点位是可行点;可以向四个方向移动,下->右->上->左; 若还不可行,则将此点位标记为不可行点;
            mazeArray[i][j] = 2;
            if (mazeArray[i + 1][j] == 0) {
                getSWay1(mazeArray,i+1, j);
                return true;
            } else if (mazeArray[i][j + 1] == 0) {
                getSWay1(mazeArray,i, j+1);
                return true;
            } else if (mazeArray[i - 1][j] == 0) {
                getSWay1(mazeArray,i-1, j);
                return true;
            } else if (mazeArray[i][j - 1] == 0) {
                getSWay1(mazeArray,i, j-1);
                return true;
            } else {
                mazeArray[i][j] = 3;
                return false;
            }
        } else {
            //点位的其余情况,直接不通过;
            return false;
        }
    }
}

执行

通行前的迷宫===>
1	1	1	1	1	1	1	
1	0	0	0	0	0	1	
1	1	1	0	0	0	1	
1	1	1	1	1	0	1	
1	0	0	0	0	0	1	
1	0	0	0	0	0	1	
1	0	0	0	0	0	1	
1	1	1	1	1	1	1	
true
下右上左==>通行后的迷宫===>
1	1	1	1	1	1	1	
1	2	2	2	0	0	1	
1	1	1	2	2	2	1	
1	1	1	1	1	2	1	
1	0	0	0	0	2	1	
1	0	0	0	0	2	1	
1	0	0	0	0	2	1	
1	1	1	1	1	1	1	

当然,也可以采用其他的方向;
比如:上 ->右 ->下-> 左

public class MazeDemo {
    public static void main(String[] args) {

        //定义二维数组作为迷宫;
        int[][] mazeArray = new int[8][7];
        //规定:  0 -> 表示没走的点;  1 ->表示围墙; 2 ->表示走过的可行点; 3 ->表示走过的不可行点;
        //先初始化构造迷宫; 上下左右用围墙; 以及中间几个特殊点作为围墙;
        for (int i = 0; i < 7; i++) {
            mazeArray[0][i] = 1;
            mazeArray[7][i] = 1;
        }
        for (int i = 0; i < 8; i++) {
            mazeArray[i][0] = 1;
            mazeArray[i][6] = 1;
        }
        //其他围墙
        mazeArray[2][1] = 1;
        mazeArray[2][2] = 1;
        mazeArray[3][1] = 1;
        mazeArray[3][2] = 1;
        mazeArray[3][3] = 1;
        mazeArray[3][4] = 1;

        //输出查看原迷宫;
        System.out.println("通行前的迷宫===>");
        for (int[] ints : mazeArray) {
            for (int i : ints) {
                System.out.print(i + "t");
            }
            System.out.println();
        }

        //执行方式2;
        boolean result = getSWay2(mazeArray, 1, 1);
        System.out.println(result);
        System.out.println("上右下左==>通行后的迷宫===>");
        for (int[] ints : mazeArray) {
            for (int i : ints) {
                System.out.print(i + "t");
            }
            System.out.println();
        }
    }

    
    public static boolean getSWay2(int[][] mazeArray, int i, int j) {
        //定义结束点;
        if (mazeArray[6][5] == 2) {
            return true;
        }
        //若点位为0,即初始点;
        if (mazeArray[i][j] == 0) {
            //假设取到的点位是可行点;可以向四个方向移动,上->右->下->左; 若还不可行,则将此点位标记为不可行点;
            mazeArray[i][j] = 2;
            if (getSWay2(mazeArray,i-1, j)) {
                return true;
            } else if (getSWay2(mazeArray,i, j+1)) {
                return true;
            } else if (getSWay2(mazeArray,i+1, j)) {
                return true;
            } else if (getSWay2(mazeArray,i, j-1)) {
                return true;
            } else {
                mazeArray[i][j] = 3;
                return false;
            }
        } else {
            //点位的其余情况,直接不通过;
            return false;
        }
    }
}

执行的路径

通行前的迷宫===>
1	1	1	1	1	1	1	
1	0	0	0	0	0	1	
1	1	1	0	0	0	1	
1	1	1	1	1	0	1	
1	0	0	0	0	0	1	
1	0	0	0	0	0	1	
1	0	0	0	0	0	1	
1	1	1	1	1	1	1	
true
上右下左==>通行后的迷宫===>
1	1	1	1	1	1	1	
1	2	2	2	2	2	1	
1	1	1	0	0	2	1	
1	1	1	1	1	2	1	
1	0	0	0	0	2	1	
1	0	0	0	0	2	1	
1	0	0	0	0	2	1	
1	1	1	1	1	1	1	

3.八皇后问题

问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。

本次解决思路,采用一维数组来表示每个皇后的位置;数组的下标索引作为皇后所在的行(从零开始的);
数组的元素值作为皇后的所在列位置

public class EightQueens {
    public static void main(String[] args) {
        EightQueens eq = new EightQueens();
        //从第1个皇后开始; 即0;
        eq.addQueen(0);
        System.out.println("总共的解法为->"+count);
    }
    //定义时,考虑使用 一个一维数组解决即可;数组的索引下标表示行(从零开始的); 数组的元素表示当前皇后所在的列;
    int queen = 8;
    int[] queenArray = new int[queen];
    //统计问题的解法;
    static int count = 0;

    //输出皇后的方法;
    private  void getQueenArray(){
       //记录被调用的次数;
        count ++;
        for (int j : queenArray) {
            System.out.print(j + "t");
        }
        System.out.println();
    }

    //添加皇后时,判断是否冲突问题; q: 表示第几个皇后;
    private boolean isConflict(int q){
        for (int i = 0; i < q; i++) {
            //不在同一列;且不在间隔对角线;
            if(queenArray[q]==queenArray[i] || Math.abs(q-i)==Math.abs(queenArray[q]-queenArray[i])){
                return false;
            }
        }
        return true;
    }

    //添加皇后; 第几个皇后;
    public void addQueen(int num){
        //添加结束;
        if(num == queen){
            getQueenArray();
            return;
        }
        for (int i = 0; i < queen; i++) {
            //添加;
            queenArray[num] =i;
            //若添加皇后时不冲突;
            if(isConflict(num)){
                addQueen(num+1);
            }
        }
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5121560.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-17
下一篇2022-11-17

发表评论

登录后才能评论

评论列表(0条)

    保存