圖的連通性和連通分量
阿新 • • 發佈:2018-12-25
1、無向圖的連通性
運用深度優先搜尋或廣度優先搜尋遍歷無向圖可以分析圖的連通性。可通過額外設定計數器count(初始值0)統計出圖的連通分量,每呼叫一次,計數器count增1。當遍歷完無向圖時,若count=1,則圖連通,若count>1,圖非連通,count的值就是該圖的連通分量數。
2、有向圖的連通性#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; }
求有向圖的強連通分量,可以使用十字連結串列儲存,利用深度優先非遞迴搜尋遍歷。
(1)在有向圖G上,按出弧表深度優先非遞迴搜尋遍歷有向圖G。
從某頂點v出發,沿以v為弧尾的弧進行深度優先非遞迴遍歷,並對深度優先非遞迴搜尋遍歷演算法修改,使被訪問過的頂點(下標)入棧,按頂點(下標)退桟的次序將頂點順序記錄在另一個數組outstack[MaxSize]。若依次不能遍歷完圖中所有頂點,再任取下一個未被訪問過的頂點出發遍歷,重複上述,直到圖中所有頂點被訪問完。outstack設計為全域性陣列,全部頂點都記錄在其中,其中頂點順序和深度優先遍歷順序相反。
(2)統計連通分量數的計數器count置1。按入弧表對圖進行深度優先非遞迴搜尋遍歷。取outstack最後的頂點,從該頂點出發,沿著以該頂點為弧頭的弧做逆向(按入弧表)深度優先非遞迴比遍歷。若此次不能遍歷完圖中頂點,則從餘下的頂點中最後完成搜尋遍歷的頂點出發,即outstack中由後往前的未被訪問頂點繼續做逆向深度優先非遞迴遍歷,直至有向圖中所有頂點都被逆向深度優先遍歷。每一次做逆向遍歷,count增1。每一次逆向遍歷所訪問到的頂點就是一個強連通分量的頂點集,count是強連通分量數。