图的遍历(Java)-广度优先搜索BFS和深度优先搜索DFS

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/AivenZhong/article/details/82255882

以前是用教科书学的图的遍历,书里的搜索算法是基于邻接矩阵和邻接表而写的,在遇到二维图的时候,其实可以直接基于二维数组写搜索算法。在网上也看到一些别人写的代码,也是在二维数组上通过查找上下左右四个方向来遍历,所以我也用Java实现了基于二维数组的广度和深度遍历。

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

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<Node> 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

猜你喜欢

转载自blog.csdn.net/AivenZhong/article/details/82255882