图论系列之「深度优先遍历及联通分量」

图的深度优先遍历及联通分量#

一、介绍#

  1. 深度优先遍历 (Depth First Search) 的主要思想是首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点。当没有未访问过的顶点时,则回到上一个顶点,继续试探别的顶点,直至所有的顶点都被访问过。

  2. 联通分量,无向图 G 的一个极大连通子图称为 G 的一个连通分量(或连通分支)。连通图只有一个连通分量,即其自身;非连通的无向图有多个连通分量。连通分量与连通分量之间没有任何边相连。深度优先遍历可以用来求连通分量。

下图有 3 个联通分量:
图论系列之「深度优先遍历及联通分量」

二、遍历过程#

如下图:
以邻接表为例
遍历过程中需要注意的是:遍历到 x 节点时,同样遍历方向会向第 x 行移动,如果 x 行为空,则会返回到原来的行
图论系列之「深度优先遍历及联通分量」

从 0 开始遍历:(0 遍历完后向第 0 行继续遍历)
图论系列之「深度优先遍历及联通分量」

然后遍历 1:(遍历 1 时已经在第 1 行,)
图论系列之「深度优先遍历及联通分量」

遍历第 1 行时,第 1 行后续只有 0 (0 已被遍历然后返回第 0 行),所以开始遍历 2 (同时遍历方向也向第 2 行)
图论系列之「深度优先遍历及联通分量」

同理
返回到了第 0 行,遍历 5,同时遍历方向变成了第 5 行
图论系列之「深度优先遍历及联通分量」

第 5 行的后续第一个节点是 0 (已被遍历), 接着往后走就是节点 3

图论系列之「深度优先遍历及联通分量」

遍历完节点 3 后,看第 3 行的后续是节点 4,遍历节点 4
图论系列之「深度优先遍历及联通分量」

同理现在就该遍历 6 了
图论系列之「深度优先遍历及联通分量」
至此图的遍历就完成了
图论系列之「深度优先遍历及联通分量」

三、代码实现#

#include <iostream>
#include <cassert>
using namespace std;

//求无权图的联通分量
template <typename Graph>
class Component{
private:
    Graph &G; //图的引用
    bool *visited; //记录深度遍历已经被访问过的节点
    int ccount; //记录联通分量
    int *id; //每个节点对应的联通分量

//dfs遍历
void dfs(int v){

    visited[v] = true;
    id[v] = ccount;
    //传入迭代器
    typename Graph::adjIterator adj(G, v);
    for(int i = adj.begin(); !adj.end(); i = adj.next()){
           if(!visited[i]){
               dfs(i);
           }
    }
}

public:
    //构造函数,求无权图的联通分量
  Component(Graph &graph):G(graph){

        //算法初始化
      id = new int[G.V()];
      visited = new bool[G.v()];
      ccount = 0;
      for(int i = 0; i < G.v(); i++){
              visited[i] = false;
              id[i] = -1;
      }

      for(int i = 0; i < G.v(); i++){    //对子图的遍历
            //如果visited[i]没有被访问过
            if(!visited[i]){
                dfs(i);
                ccount ++;
            }
       }
    }

//析构函数
  ~Component(){
        delete[] visited;
        delete[] id;
  }

  //返回图的联通分量
  int count(){
        return ccount;
  }

  //查询v和w是否联通
  bool isComponent(int v, int w){
        assert( v >= 0 && v < G.V() );
        assert( w >= 0 && w < G.V() );
        return id[v] = id[w];
   }
};
本作品采用《CC 协议》,转载必须注明作者和本文链接
刻意学习
未填写
文章
122
粉丝
103
喜欢
187
收藏
274
排名:344
访问:2.8 万
私信
所有博文
社区赞助商