无向图 广度优先搜索 和 深度优先搜索

Posted jamesddream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无向图 广度优先搜索 和 深度优先搜索相关的知识,希望对你有一定的参考价值。

代码如下

/**
 * 无向图
 */
public class Graph {
    public int v;//顶点个数
    public List<Integer> adj[];//邻接表

    public static void main(String[] args) {
        Graph graph = constructGraph();
        graph.bfs(0, 6);
        graph.dfs(0, 6);
    }

    /**
     * 构建测试图
     */
    private static Graph constructGraph() {
        /**
         * <pre>
         * 构造图
         * 搜索元素 0 到 6 的路径
         *
         *   0 —— 1 —— 2
         *   |    |    |
         *   3 —— 4 —— 5
         *        |    |
         *        6 —— 7
         *
         * 用广度优先搜索算法 和 深度优先搜索算法 分别进行处理
         * </pre>
         */

        // 8个定点
        Graph graph = new Graph(8);
        // 添加边
        graph.addEdge(0, 1).addEdge(1, 2).
                addEdge(0, 3).addEdge(1, 4).addEdge(2, 5).
                addEdge(3, 4).addEdge(4, 5)
                .addEdge(4, 6).addEdge(5, 7)
                .addEdge(6, 7);
        return graph;
    }

    public Graph(int v) {
        this.v = v;
        adj = new LinkedList[v];
        for (int i = 0; i < v; i++) {
            adj[i] = new LinkedList<>();
        }
    }

    public Graph addEdge(int s, int t) {
        adj[s].add(t);
        adj[t].add(s);
        return this;
    }

    /**
     * 广度优先搜索 Breadth-First-Search
     * <p>
     * (1)visited 是用来记录已经被访问的顶点,用来避免顶点被重复访问。
     * 如果顶点 q 被访问,那相应的 visited[q]会被设置为 true。
     * <p>
     * (2)queue 是一个队列,用来存储已经被访问、但相连的顶点还没有被访问的顶点。
     * 因为广度优先搜索是逐层访问的,也就是说,我们只有把第 k 层的顶点都访问完成之后,
     * 才能访问第 k+1 层的顶点。当我们访问到第 k 层的顶点的时候,我们需要把第 k 层的顶点记录下来,
     * 稍后才能通过第 k 层的顶点来找第 k+1 层的顶点。所以,我们用这个队列来实现记录的功能。
     * <p>
     * (3)prev 用来记录搜索路径。当我们从顶点 s 开始,广度优先搜索到顶点 t 后,prev 数组中存储的就是搜索的路径。
     * 不过,这个路径是反向存储的。prev[w]存储的是,
     * 顶点 w 是从哪个前驱顶点遍历过来的。比如,我们通过顶点 2 的邻接表访问到顶点 3,那 prev[3]就等于 2。
     * 为了正向打印出路径,我们需要递归地来打印,你可以看下 print() 函数的实现方式。
     */
    public void bfs(int s, int t) {
        System.out.println("bfs:");
        if (s == t) return;
        boolean[] visited = new boolean[v];
        Queue<Integer> queue = new LinkedList<>();
        queue.add(s);
        int[] prev = new int[v];
        for (int i = 0; i < v; i++) {
            prev[i] = -1;
        }
        while (queue.size() != 0) {
            int w = queue.poll();
            for (int i = 0; i < adj[w].size(); i++) {
                int q = adj[w].get(i);
                if (!visited[q]) {
                    prev[q] = w;
                    if (q == t) {
                        print(prev, s, t);
                        return;
                    }
                    visited[q] = true;
                    queue.add(q);
                }
            }
        }
    }

    boolean found = false;

    /**
     * 深度优先搜索 Depth-first-search
     */
    public void dfs(int s, int t) {
        System.out.println("dfs:");
        found = false;
        boolean[] visited = new boolean[v];
        int[] prev = new int[v];
        for (int i = 0; i < v; i++) {
            prev[i] = -1;
        }
        recurDfs(s, t, visited, prev);
        print(prev, s, t);
    }

    private void recurDfs(int w, int t, boolean[] visited, int[] prev) {
        if (found) return;
        visited[w] = true;
        if (w == t) {
            found = true;
            return;
        }
        for (int i = 0; i < adj[w].size(); i++) {
            int q = adj[w].get(i);
            if (!visited[q]) {
                prev[q] = w;
                recurDfs(q, t, visited, prev);
            }
        }
    }

    private void print(int[] prev, int s, int t) {
        if (prev[t] != -1 && t != s) {
            print(prev, s, prev[t]);
        }
        System.out.println(t + "  ");
    }
}

执行main方法,打印结果如下

bfs:
0  
1  
4  
6  
dfs:
0  
1  
2  
5  
4  
6

 

以上是关于无向图 广度优先搜索 和 深度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章

无向图的深度优先搜索和广度优先搜索

深度优先搜索和广度优先搜索

图解:深度优先搜索与广度优先搜索

算法_图的深度优先搜索和广度优先搜索

深度优先搜索和广度优先搜索的简单对比

c语言图的遍历,邻接表存储,深度,广度优先遍历