基于二维矩阵的深搜dfs和广搜bfs Java实现

广搜的概念不用多讲了,这里的算法主要针对二维矩阵(迷宫)的广搜。

二维矩阵中的点一般只与上下左右4个结点相邻,看题目定义,有的和斜角也相邻。所以就没必要用邻接矩阵存边数据,直接搜就可以啦。

与传统bfs不同的数据结构:
graph(二维矩阵图)
vis(二维标记,标记对应位置是否访问过)
direction(存行走方向,比如往左走就是{0,-1},表示 i 不变,j 减一嘛,同理右{0,1},上 {-1,0},下{1,0})
node(存点的位置 {x, y})

步骤不多说啦,大同小异嘛,注意队列里是存点的位置。

这里的代码主要用一个graph类来描述一个图,然后在图里面写一个深搜算法。仅作为参考。刷题的人可以只用深搜算法即可,当然要准备好对应的数据结构啦。

//此类是用来描述一个基于二维数组的图

package Graph;

import java.util.LinkedList;

public class SimpleGraph {
    private static int nodeNum = 0;
    private static int[][] graph;
    private static int[][] direction = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    private static int[][] visited;

    public SimpleGraph() {}

    public SimpleGraph(int[][] graph) {
        this.graph = graph;
        visited = new int[graph.length][graph[0].length];
    }

    public int getNodeNum() {
        return nodeNum;
    }

    //广度优先搜索Breadth First Search,从点(x, y)开始,队列实现
    public void bfs(int x, int y) {
        //标记数组,标记已访问的位置和已入栈的位置
        int num = 0;
        LinkedList queue = new LinkedList<>();
        queue.add(new Node(x, y));
        while (!queue.isEmpty()) {
            Node tem = queue.poll();
            System.out.print(graph[tem.x][tem.y] + " ");
            for (int i = 0; i < direction.length; i++) {
                int tx = tem.x + direction[i][0];
                int ty = tem.y + direction[i][1];
                //越界跳过,遇到障碍或访问过的跳过,符合条件的就入队
                if (tx >= 0 && ty >= 0 && tx < graph.length && ty < graph[0].length &&
                        graph[tx][ty] > 0 && visited[tx][ty] == 0) {
                    queue.offer(new Node(tx, ty));
                    //防止入队过的元素重复入队
                    visited[tx][ty] = 1;
                }
            }
            //标记访问过的位置
            visited[tem.x][tem.y] = 1;
            num++;
        }
        nodeNum = num;
        System.out.println();
        initializeVisited();
    }

    //初始化标记数组visited
    private void initializeVisited() {
        for (int i = 0; i < visited.length; i++) {
            for (int j = 0; j < visited[0].length; j++)
                visited[i][j] = 0;
        }
    }

    //深度优先搜索Depth First Search,从点(x, y)开始,递归实现
    public void dfs(int x, int y) {
        nodeNum = 0;
        dfsTrace(x, y);
        System.out.println();
        initializeVisited();
    }

    private void dfsTrace(int x, int y) {
        System.out.print(graph[x][y] + " ");
        //标记已遍历的结点
        visited[x][y] = 1;
        nodeNum++;
        //从四个方向找可以走的路
        for (int i = 0; i < direction.length; i++) {
            int tx = x + direction[i][0];
            int ty = y + direction[i][1];
            //越界跳过,遇到障碍或访问过的跳过,符合条件的就递归
            if (tx >= 0 && ty >= 0 && tx < graph.length && ty < graph[0].length &&
                    graph[tx][ty] > 0 && visited[tx][ty] == 0) {
                dfsTrace(tx, ty);
            }
        }
    }

}

class Node {
    int x;
    int y;
    Node(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

下面是测试代码

public class TestGraph {
    public static void main(String[] args) {
        int[][] graph = {
                {1, 4, 7, 7, 3},
                {0, 2, 0, 0, 1},
                {6, 7, 5, 2, 9},
                {0, 6, 7, 8, 0},
                {0, 5, 0, 8, 4},
        };

        int[][] graph2 = {
                {0, 2, 9, 0, 0},
                {0, 1, 0, 0, 0},
                {0, 7, 5, 2, 0},
                {0, 6, 7, 8, 0},
                {0, 5, 0, 8, 4},
        };

        System.out.println("测试图的广度优先搜索");
        SimpleGraph g = new SimpleGraph(graph);
        g.bfs(2, 2);
        System.out.println(g.getNodeNum() + "\n");

        System.out.println("测试图的深度优先遍历");
        SimpleGraph g2 = new SimpleGraph(graph2);
        g2.dfs(2, 2);
        System.out.println(g2.getNodeNum());
    }
}

输出

测试图的广度优先搜索
5 2 7 7 9 8 6 2 6 1 8 5 4 3 4 7 1 7 
18

测试图的深度优先遍历
5 2 8 8 4 7 6 7 1 2 9 5 
12

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