1. 程式人生 > >圖的連通性和連通分量

圖的連通性和連通分量

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是強連通分量數。