图的连通性和连通分量

1、无向图的连通性

运用深度优先搜索或广度优先搜索遍历无向图可以分析图的连通性。可通过额外设置计数器count(初始值0)统计出图的连通分量,每调用一次,计数器count增1。当遍历完无向图时,若count=1,则图连通,若count>1,图非连通,count的值就是该图的连通分量数。


#include <iostream>
using namespace std;
#define INFINITY  65535 /* 表示权值的无穷*/
typedef int EdgeType;//边上的权值类型
typedef int VertexType;//顶点类型
const int MaxSize=100;
int visited[MaxSize];//全局标识数组
//无向图邻接表。边表结点结构
struct EdgeNode
{
    int adjvex;//邻接点域
    EdgeNode *next;//指向下一个边结点的指针
};
//无向图邻接表。表头结点结构
struct VexNode
{
    VertexType vertex;//顶点
    EdgeNode *firstedge;//边表的头指针
};
//邻接表类
class ALGraph
{
    public:
        ALGraph()//无参构造函数
        {
            vertexNum=0;
            edgeNum=0;
            for(int i=0;i<MaxSize;i++)
                adjlist[i].firstedge=NULL;
        }
        ALGraph(VertexType a[],int n);//有参构造函数
        void createGraph(int start, int end);//创建图,采取前插法
        void DFSL(int v);//从v出发深度优先遍历可达顶点递归函数
        void DFSL1(int v);//从v出发深度优先遍历可达顶点的非递归函数
        void displayGraph(int nodeNum);//打印
        void CountComp(ALGraph g);//求连通分量数,判断图的连通性
    private:
        VexNode adjlist[MaxSize];//存放顶点表的数组
        int vertexNum,edgeNum;//图的顶点数和边数
};
//有参构造函数。构造顶点表
ALGraph::ALGraph(VertexType a[],int n)
{
    vertexNum=n;
    edgeNum=0;
    for(int i=0;i<vertexNum;i++)
    {
        adjlist[i].vertex=a[i];
        adjlist[i].firstedge=NULL;
    }
}
//创建图,采取前插法
void ALGraph::createGraph(int start, int end)
{//边(start,end)
    //adjlist[start].vertex=start;//表头结点中的顶点
    EdgeNode *p=new EdgeNode;//边结点
    p->adjvex=end;//邻接点
    //p->weight=weight;
    p->next=adjlist[start].firstedge;//前插法插入边结点p
    adjlist[start].firstedge=p;
}
//打印存储的图
void ALGraph::displayGraph(int nodeNum)
{
    int i,j;
    EdgeNode *p;
    for(i=0;i<nodeNum;i++)
    {
        p=adjlist[i].firstedge;
        while(p)
        {
            cout<<'('<<adjlist[i].vertex<<','<<p->adjvex<<')'<<endl;
            p=p->next;
        }
     }
}
//从v出发深度优先遍历可达顶点递归函数
void ALGraph::DFSL(int v)
{
    int n=vertexNum;
    int j;
    EdgeNode *p;
    if(v>=n||v<0) throw "位置出错";
    cout<<adjlist[v].vertex<<" ";
    visited[v]=1;
    p=adjlist[v].firstedge;
    while(p)
    {
        j=p->adjvex;//顶点
        if(visited[j]==0) DFSL(j);
        p=p->next;
    }
}
//从v出发深度优先遍历可达顶点的非递归函数
void ALGraph::DFSL1(int v)
{
    int S[MaxSize],top=-1,j,n=vertexNum;
    EdgeNode *p;
    if(v>=n||v<0) throw "位置出错";
    cout<<adjlist[v].vertex<<" ";
    visited[v]=1;
    S[++top]=v;//v进栈
    while(top!=-1)
    {
        v=S[top--];//栈顶元素出栈
        p=adjlist[v].firstedge;
        while(p)
        {
            j=p->adjvex;//顶点
            if(visited[j]==1) p=p->next;
            else
            {
                cout<<adjlist[j].vertex<<" ";
                visited[j]=1;
                S[++top]=j;//v进栈
                p=adjlist[j].firstedge;
            }
        }
    }
}
//求连通分量数,判断图的连通性
void ALGraph::CountComp(ALGraph g)
{
    int count=0;
    int n=g.vertexNum;
    for(int v=0;v<n;v++)
    {
        if(visited[v]==0)
        {
            count++;
            g.DFSL(v);
        }
    }
    if(count==1) cout<<endl<<"改图是连通的!"<<endl;
    else cout<<endl<<"改图不连通,连通分量数为:"<<count<<endl;
}
int main()
{
    int a[8]={0,1,2,3,4,5,6,7};
    ALGraph gr=ALGraph(a,8);//初始化表头
    gr.createGraph(0,2);
    gr.createGraph(0,1);
    gr.createGraph(1,3);
    gr.createGraph(1,0);
    gr.createGraph(2,3);
    gr.createGraph(2,0);
    gr.createGraph(3,2);
    gr.createGraph(3,1);
    gr.createGraph(4,5);
    gr.createGraph(5,6);
    gr.createGraph(5,4);
    gr.createGraph(6,7);
    gr.createGraph(6,5);
    gr.createGraph(7,6);
    gr.displayGraph(8);
    for(int i=0;i<MaxSize;i++)
        visited[i]=0;
    gr.CountComp(gr);
    return 0;
}


2、有向图的连通性

求有向图的强连通分量,可以使用十字链表存储,利用深度优先非递归搜索遍历。

(1)在有向图G上,按出弧表深度优先非递归搜索遍历有向图G。

从某顶点v出发,沿以v为弧尾的弧进行深度优先非递归遍历,并对深度优先非递归搜索遍历算法修改,使被访问过的顶点(下标)入栈,按顶点(下标)退桟的次序将顶点顺序记录在另一个数组outstack[MaxSize]。若依次不能遍历完图中所有顶点,再任取下一个未被访问过的顶点出发遍历,重复上述,直到图中所有顶点被访问完。outstack设计为全局数组,全部顶点都记录在其中,其中顶点顺序和深度优先遍历顺序相反。

(2)统计连通分量数的计数器count置1。按入弧表对图进行深度优先非递归搜索遍历。取outstack最后的顶点,从该顶点出发,沿着以该顶点为弧头的弧做逆向(按入弧表)深度优先非递归比遍历。若此次不能遍历完图中顶点,则从余下的顶点中最后完成搜索遍历的顶点出发,即outstack中由后往前的未被访问顶点继续做逆向深度优先非递归遍历,直至有向图中所有顶点都被逆向深度优先遍历。每一次做逆向遍历,count增1。每一次逆向遍历所访问到的顶点就是一个强连通分量的顶点集,count是强连通分量数。



  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值