图的遍历——连通分量

7.3 图的遍历

  • 7.3.3 连通分量
    • 连通分量的概念
    • 判断是否连通 代码实现

7.3.3 连通分量

连通分量的概念

  1. 对于连通图,从任一顶点出发,只需一次调用深度优先搜索算法或广度优先搜索算法即可访问到图中的所有顶点;
    对于非连通图时,从图中某一顶点出发,一次调用深度优先搜索算法或广度优先搜索算法不可能访问到图中的所有顶点,只能访问到该顶点所在的极大连通子图(即连通分量)的所有顶点。
  2. 非连通图有k个连通分量,就要k次调用DFS或BFS才能访问图中的所有顶点。若从图的每一个连通分量中的一个顶点出发进行搜索,就可以求得图的所有连通分量。
    所谓连通分量,是指非连通图中极大连通子图
  3. 在实际的遍历算法中,需要检测图的每一个顶点:若顶点已被访问过,则该顶点一定是落在图中已求得的连通分量上;若顶点还未被访问,则从该顶点出发遍历图,可求得图的另一个连通分量。图7-4给出一个非连通无向图及其连通分量的示例。对此图进行深度优先遍历或广度优先遍历,将三次调用DFS或BFS过程:第一次从顶点A出发,第二次从顶点F出发。第三次从顶点1出发,最后得到原图的三个连通分量。
    图的遍历——连通分量_第1张图片
    对于非连通图的每一个连通分量,其中的所有顶点和用某种遍历方式所经过的边的集合,构成了一棵生成树,这是一个极小连通子图。所有连通分量的生成树组成了非连通图的生成森林,如图7-17(a)和图7-17(b)分别是图7-4所示非连通图的深度优先生成森林和广度优先生成森林。

判断是否连通 代码实现

///广度优先遍历思路
template <class ElemType>
bool BFStestConnect(const AdjMatrixUndirGraph<ElemType> &g, void (*Visit)(const ElemType &))
{
    int v,w,count;
    ElemType e;
    for (v = 0; v < g.GetVexNum(); v++)
        g.SetTag(v, UNVISITED); // 对每个顶点作未访问标志
    queue<int> q;
    count=0;//用count记录已经访问过的顶点数

    v=0;//判断是否连通的起始点

    g.SetTag(v, VISITED);						// 作访问标志
	g.GetElem(v, e);							// 取顶点v的数据元素值
	Visit(e);									// 访问顶点v
  	count++;
    q.push(v);	                            // 顶点v入队

    while(!q.empty())
    {
        v=q.front();
        q.pop();
        for (w = g.FirstAdjVex(v); w != -1; w = g.NextAdjVex(v, w))
        {
            if (g.GetTag(w) == UNVISITED)  // 对u尚未访问过的邻接顶点w进行访问
            {
                g.SetTag(w, VISITED);
                g.GetElem(w, e);
                Visit(e);
                count++;
                q.push(w);
            }
        }
    }
    if(count==g.GetVexNum())
    {
        cout<<"Graph Is Connect."<<endl;
        return true;
    }
    else//说明图不连通,即存在回路
    {
        cout<<"Graph Is Not Connect."<<endl;
        return false;
    }
}

///深度优先遍历思路
template <class ElemType>
bool DFStestConnect(const AdjMatrixUndirGraph<ElemType> &g, void (*Visit)(const ElemType &))
{
    int v,w,count;
    for (v = 0; v < g.GetVexNum(); v++)
        g.SetTag(v, UNVISITED);// 对每个顶点设置未访问标志
    ElemType e;
    stack<int> s;
    count=0;
    
    v=0;
    while(g.GetTag(v) == UNVISITED)
    {
        if(g.GetTag(v) == UNVISITED)
        {
            g.SetTag(v, VISITED);		// 设置顶点v已访问标志
            g.GetElem(v, e);			// 取顶点v的数据元素值
            Visit(e);					// 访问顶点v
            count++;
            s.push(v);

            for (w = g.FirstAdjVex(v); w != -1; w = g.NextAdjVex(v, w))
            {
                if(g.GetTag(w) == UNVISITED)
                {
                    v=w;
                    break;
                }
            }
            if(w!=-1)
                continue;
        }
        while(!s.empty())
        {
            v=s.top();
            for (w = g.FirstAdjVex(v); w != -1; w = g.NextAdjVex(v, w))
            {
                if(g.GetTag(w) == UNVISITED)
                {
                    v=w;
                    break;
                }
            }
            if(w==-1)
            {
                s.pop();
            }
            else
                break;
        }
    }
    if(count==g.GetVexNum())
    {
        cout<<"Graph Is Connect"<<endl;
        return true;
    }
    else
    {
        cout<<"Graph Is Not Connect"<<endl;
        return false;
    }
}

你可能感兴趣的:(#,数据结构)