20230329 6.2. 图的遍历

深度优先搜索(Depth First Search, DFS)

void DFS ( Vertex V ) 
{ 
    visited[ V ] = true; 
    for ( V 的每个邻接点 W )
        if ( !visited[ W ] )
            DFS( W );
}

若有N个顶点、E条边,时间复杂度是

  • 用邻接表存储图,有O(N+E)
  • 用邻接矩阵存储图,有O(N2)

广度优先搜索(Breadth First Search, BFS)

void BFS ( Vertex V ) 
{ 
    visited[V] = true;
    Enqueue(V, Q);
    while(!IsEmpty(Q)){
        V = Dequeue(Q); 
        for ( V 的每个邻接点 W )
            if ( !visited[W] ) {
                visited[W] = true;
                Enqueue(W, Q);
            }
    }
}

若有N个顶点、E条边,时间复杂度是

  • 用邻接表存储图,有O(N+E)
  • 用邻接矩阵存储图,有O(N2)

图不连通怎么办?

  • 连通:如果从V到W存在一条(无向)路径,则称V和W是连通的
  • 路径:V到W的路径是一系列顶点{V, v1, v2, …, vn, W}的集合,其中任一对相邻的顶点间都有图中的边。
    • 路径的长度是路径中的边数(如果带权,则是所有边的权重和)。如果V到W之间的所有顶点都不同,则称简单路径
  • 回路:起点等于终点的路径
  • 连通图:图中任意两顶点均连通
  • 连通分量:无向图的极大连通子图
    • 极大顶点数:再加1个顶点就不连通了
    • 极大边数:包含子图中所有顶点相连的所有边
  • 强连通:有向图中顶点V 和 W之间存在双向路 径,则称V 和 W是强连通的
  • 强连通图:有向图中任意两顶点均强连通
  • 强连通分量:有向图的极大强连通子图

每调用一次DFS(V),就把V所在的连通分量遍历了一遍。BFS也是一样。

代码实现

邻接矩阵

boolean[] visited;

/**
    * 深度优先
    *
    * @param i 遍历起始节点索引
    */
public void dfs(int i) {
    visited[i] = true;
    Console.log(i);

    // 遍历node的所有出度,也就是行非0的元素
    for (int w = 0; w < edges[i].length; w++) {
        if (edges[i][w] == 1 && !visited[w]) {
            dfs(w);
        }
    }
}

/**
    * 广度优先
    *
    * @param i 遍历起始节点索引
    */
public void bfs(int i) {
    boolean[] visited = new boolean[size];
    Queue<Integer> queue = new LinkedList<>();

    visited[i] = true;
    queue.offer(i);
    Console.log(i);

    while (!queue.isEmpty()) {
        int v = queue.poll();
        for (int w = 0; w < edges[v].length; w++) {
            if (edges[v][w] == 1 && !visited[w]) {
                visited[w] = true;
                queue.offer(w);
                Console.log(w);
            }
        }
    }
}

邻接链表

List<Integer> visited;

/**
    * 深度优先
    *
    * @param id 遍历起始节点索引
    */
public void dfs(int id) {
    visited.add(id);
    Console.log(id);

    // 遍历node的所有出度,也就是行非0的元素
    LinkedGraphNode node = edges[id];
    while (node != null) {
        if (!visited.contains(node.id)) {
            dfs(node.id);
        }
        node = node.next;
    }
}

/**
    * 广度优先
    *
    * @param id 遍历起始节点索引
    */
public void bfs(int id) {
    List<Integer> visited = ListUtil.toList();
    Queue<Integer> queue = new LinkedList<>();

    visited.add(id);
    queue.offer(id);
    Console.log(id);

    while (!queue.isEmpty()) {
        int v = queue.poll();

        LinkedGraphNode node = edges[v];
        while (node != null) {

            int w = node.id;
            if (!visited.contains(w)) {
                visited.add(w);
                queue.offer(w);
                Console.log(w);
            }

            node = node.next;
        }
    }
}

posted @ 2023-06-21 16:23  流星<。)#)))≦  阅读(0)  评论(0编辑  收藏  举报