数据结构与算法之递归(迷宫回溯问题)

什么是递归:顾名思义,递归就是自己调用自己。我自己理解递归的本质是不断的开辟方法栈的过程

/**
 * 迷宫回溯
 */
public class MazeBacktrack {

    public static void main(String[] args) {
        // 构造一个7行6列的地图矩阵
        int[][] map = new int[7][6];
        // 第一行和最后一行都是"墙", 用数字1来表示
        for (int i = 0; i < 6; i++) {
            map[0][i] = 1;
            map[6][i] = 1;
        }
        // 第1列和最后一列也都是"墙", 也用数字1来表示
        for (int i = 0; i < 7; i++) {
            map[i][0] = 1;
            map[i][5] = 1;
        }
        // 第3行的第2列以及第3行的第3列也是墙, 也用数字1来表示
        map[3][1] = 1;
        map[3][2] = 1;
        // 查看整个地图的构造情况
        for (int i = 0; i < 7; i++) {
            for (int j = 0; j < 6; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
        // 策略为上下左右
        setWay(map, 5, 1);
        // 再次查看整个地图的构造情况
        System.out.println("走出路径之后: ");
        List list = new ArrayList<>();
        for (int i = 0; i < 7; i++) {
            for (int j = 0; j < 6; j++) {
                if (map[i][j] == 2) {
                    list.add(2);
                }
            }
        }
        System.out.printf("上下左右策略, 共走了%d步", list.size());
    }

    private static boolean setWay(int[][] map, int i, int j) {
        if (map[5][4] == 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 + 1, j)) {
                    return true;
                } else if (setWay(map, i, j - 1)) {
                    return true;
                } else if (setWay(map, i, j + 1)) {
                    return true;
                } else {
                    map[i][j] = 3;
                    return false;
                }
            } else {
                return false;
            }
        }
    }
}

画图分析一波(由于我选的这个移动策略太沙雕了,我就只画了一部分,这一部分也很有助于理解了,整个流程全画完太长了,估计到时候没耐心看了):

数据结构与算法之递归(迷宫回溯问题)_第1张图片

数据结构与算法之递归(迷宫回溯问题)_第2张图片

数据结构与算法之递归(迷宫回溯问题)_第3张图片

每次向下一个方向探索时都会在当前坐标点的基础上重新开栈,依次类推,直接遇到这个方向无路可走,就退回到前一个栈,重新开栈,走下一个方向。

// 测试的结果
1 1 1 1 1 1 
1 0 0 0 0 1 
1 0 0 0 0 1 
1 1 1 0 0 1 
1 0 0 0 0 1 
1 0 0 0 0 1 
1 1 1 1 1 1 
走出路径之后: 
1 1 1 1 1 1 
1 3 3 2 2 1 
1 3 3 2 2 1 
1 1 1 2 2 1 
1 2 2 2 2 1 
1 2 2 2 2 1 
1 1 1 1 1 1 
上下左右策略, 共走了14步

查看上面的结果,我们发现,采用上下左右策略走迷宫的话一共走了14步(确实够沙雕)。我们可以观察一下数字3所在的位置,然后分析一波:

  • 在走到坐标为(2,2)这个位置,将这个位置标记为2之后,我们可以发现上下左右都不能走了,根据代码逻辑如果上下左右都不能走,我们就只能把该位置设置成3表示该位置是死路,所以回到坐标为(3,2)的栈中。
  • 在坐标为(3,2)这个栈中,之前我们已经把该坐标位置的值设置为2了(原因:走路策略是上下左右),我们发现上下左右也不能走(上:3,下:1,左:1,右:2),所以这个位置也设置3,然后返回坐标为(3,3)的栈中。
  • 在坐标为(3,3)这个栈中,此时该坐标位置的值是2(原因同上),我们发现同样上下左右不能走,同样的该位置的值设为3,然后返回坐标为(2,3)的栈中。
  • 在坐标为(3,3)这个栈中,时该坐标位置的值是2(原因同上),我们发现上下左不能走(上:1,下:3,左:3),右边能走(右:0),所以此时在坐标为(3,4)的位置重新开栈,依次类推。

最终我们从死路(2,2)这个位置回到了(2,3)这个位置,继续向可以走的方向(右)继续探索,这就是回溯。

我学习的感受:递归如果单纯的用脑子想是不太容易理解的,如果想搞清楚的话,就开栈画图。搞清楚每一步在哪个方法栈里面,在该栈走到了哪个if判断。感觉这种方式对我学习递归大有裨益,也希望大家可以尝试一下。

无他,唯手熟尔!!!

 

你可能感兴趣的:(数据结构与算法)