数据结构小白之递归及其简单应用

递归的含义

递归简单来说,就是“我调我自己”,从方法上而言,就是方法自己调用自己,递归有助于解决复杂的问题,同时使得代码可以更加简洁。

举个栗子

public class demo1 {
    public static void main(String[] args) {
        test(5);
    }

    //顺序输出
    public static void test(int n) {
        if (n > 2) {
            //test(4)->test(3)->test(2) 栈
            test(n - 1);
        }
        System.out.println("n:" + n);
    }

   
}

注:在这里举了个阶乘计算的栗子,接下来从底层分析一个方法调用的详细情况

当程序执行一个方法的时候,就会为该方法开辟一个栈区,由于使用的方法是递归,当调用方法时,在栈中就会形成如图所示的调用顺序(可以把程序的上下级的互调想象为压栈)。然后把程序的回溯想象为出栈,所以程序的输出为2 3 4 5 (test(2) test(3) test(4) test(5)分别出栈)【个人想法,可能不太严谨...】

递归可以解决的问题:

1.数学问题: 8皇后问题,汉诺塔问题,迷宫问题等

2.各种算法也会使用到递归,比如说快排,归并,二分,分治算法

3.用栈可以解决的问题,使用递归将会更加简单

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

1.执行一个方法时,就创建一个新的受保护的独立空间(栈)

2.方法的局部变量是独立的,不会相互影响

3.如果方法使用的是引用类型的变量,就会共享该引用类型的数据

4.递归必须要向退出递归的条件逼近,否则会出现严重的后果 StackOverFlowError
5.当一个方法执行完后,或者遇到了return就会返回给方法的调用者。谁调用它就把结果返回给谁

递归的简单应用(迷宫问题)

假设有一个 8*7的迷宫,规定如下: 如果编号为0,表示未涉及的区域,如果编号为1,表示为迷宫的墙壁,如果编号为2表示可以走,如果编号为3表示此路不通

假设从点x,y 需要走到点[6,5],该如何进行路径规划呢?

代码实现

1.准备使用二维数组来模拟迷宫(左右前后全部置为1)

        int[][]map=new int[8][7];
        //使用1 表示墙
        //上下全部置为1
      for(int i=0;i<7;i++){
          map[0][i]=1;
          map[7][i]=1;
      }
        //左右全部置为1
      for(int i=0;i<8;i++){

          map[i][0]=1;
          map[i][6]=1;
      }
        //设置迷宫挡板
        map[3][1]=1;
        map[3][2]=1;
       //初始化完毕,开始输出地图
        for (int[] ints : map) {
            for (int i : ints) {
                System.out.print(i+"    ");
            }
            System.out.println();
        }

2.使用递归回溯的方法来进行找路

 //使用递归回溯来给小球找路
    /**
     * 1. map表示地图
     * 2. i j从【1,1】位置开始找,如果小球可以到map[6,5].则说明通路找到了
     * 3. 如果找到通路了就返回true 否则返回false
     * 4. 当map[i][j]=0的时候,表示该店还没有走过,当为1表示墙,当为2表示是一个通路,可以走;如果是3表示该位置已经走过,但是走不通
     * 5. 在走迷宫的时候需要确定一个策略(方法),下->右->上->左,如果该点走不通,就再回溯
     * */
    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;
                }

            }
            //map[i][j]!=0? 可能是1 2 3
            else{
                return false;
            }
        }
    }

注:在进行找路的时候,可以通过不同的策略来进行不同路径的选取。由于这里并不是对于后续最短距离算法的探讨,所以并没有使用任何算法来进行路径的筛选。而是单纯通过递归,通过不同策略的回溯来进行选取策略(后期会对算法进行修改,加上最短路径的获取)

输出结果: 由数字2组成的就是路径

完整代码:https://github.com/Lzin/recursion

发布了193 篇原创文章 · 获赞 70 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/Lzinner/article/details/102783479