圖(有向圖)的應用——拓撲排序
阿新 • • 發佈:2019-02-11
1、基本概念:
有序圖,每個頂點都有前驅和後繼的關係。
現實生活中我們可以用一個有向圖來表示一個工程,頂點表是活動,有向邊A---------->B表示:A必須先於活動B進行。這種有向圖叫做“ 頂表示活動的網路(activity on vertices)”
——記作AOV網路。
將全部頂點都排在一個線性有序的序列中。這種構造AOV網路全部頂點的拓撲有序序列的運算就叫做拓撲排序(topological sorting)
2、步驟:
(1)選擇一個沒有直接前驅的頂點,並輸出;
(2)從圖中刪除該頂點,同時刪去所有它發出的有向邊;
(3)依次迴圈以上兩步,直到:全部頂點已經輸出(排序結束),或被迫跳出迴圈(圖中存在環)
(注意理解程式碼中有個模仿棧結構的top“指標”和count入度陣列)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void TopologicalSort() { int i,top=-1; for(i = 0;i<numVertexs;++i) { if(count[i] == 0) { count[i] = top; top = i;//top是用下標表示 } } for(i = 0;i<numVertexs;++i) { if(top == -1) cout<<"Have a circle..."<<endl; else { int j = top; top = count[j]; cout<<myv[j].data<<"-->"; EdgeNode *l = myv[j].link; while(l) { int k = l->dest; if(--count[k] == 0)//這裡的--是將l所指出去相連的邊都刪掉。 { count[k] = top; top = k; } l = l->next; } } } }
#pragma once #include"AllHead.h" #define MAXSIZE 20 //單向圖。 class EdgeNode; template<class T> class GrapHVec; template<class T> class VertexList { friend class GrapHVec<T>; private: T data; EdgeNode *link; public: VertexList():link(NULL) {} ~VertexList(){} }; class EdgeNode { public: int dest; EdgeNode *next; public: EdgeNode() { next = NULL; } ~EdgeNode(){} }; template<class T> class GrapHVec { private: VertexList<T> *myv; int maxSize;//最大 int numVertexs; int numEdges; int *count;//建立一個入度陣列 public: GrapHVec(int sz=MAXSIZE) { maxSize = sz<=MAXSIZE?MAXSIZE:sz; myv = new VertexList<T>[maxSize]; count = new int[maxSize]; for(int i=0;i<maxSize;++i) count[i] = 0; numVertexs = 0; numEdges = 0; } ~GrapHVec(){} public: int GetNextNeighbor(T x1,T x2) { if(numVertexs == 0) { cout<<"空(GetFirstNeighbor)..."; return ERROR; } int v1 = GetVerticespos(x1); int v2 = GetVerticespos(x2); EdgeNode *fp = myv[v1].link; while(fp!=NULL && (*fp).dest != v2) fp = (*fp).next; if(fp == NULL) { //cout<<"不存在有過連結....."; return -1; } fp = (*fp).next; if(fp != NULL) return (*fp).dest; else { //cout<<"沒有下一個結點...."; return -1; } } int GetFirstNeighbor(T x) { if(numVertexs == 0) { cout<<"空(GetFirstNeighbor)..."; return ERROR; } int v = GetVerticespos(x); EdgeNode *fp = myv[v].link; if(fp != NULL) return (*fp).dest; else { cout<<x<<" :沒有連結的結點...."; return ERROR; } } int GetVerticespos(T x) { if(numVertexs == 0) { cout<<"空(Getpos)...."; return FALSE; } int i; for(i=0;i<numVertexs;i++) { if(myv[i].data == x) return i; } return -1; } public: int NumOfVertices(){return numVertexs;} int NumOfEdge(){return numEdges;} int InsertVertex(T x) { if(numVertexs >= maxSize) { cout<<"空間已滿不能插入...."<<endl; return ERROR; } myv[numVertexs++].data = x; return TRUE; } int InsertEdge(T x1,T x2)//A,B:A-->B { int v1 = GetVerticespos(x1);//A int v2 = GetVerticespos(x2);//B if(v1 == -1||v2 == -1) { cout<<"有一個節點不存在"<<endl; return ERROR; } EdgeNode *p1 = new EdgeNode; (*p1).dest = v2; (*p1).next = myv[v1].link; myv[v1].link = p1; count[v2]++; ++numEdges; } void showVecGrap() { for(int i=0; i<numVertexs; ++i) { cout<<i<<":>"<<myv[i].data<<"-->"; EdgeNode *e = myv[i].link; while(e != NULL) { cout<<e->dest<<"-->"; e = e->next; } cout<<"Nul."<<endl; } } public: void TopologicalSort() { int i,top=-1; for(i = 0;i<numVertexs;++i) { if(count[i] == 0) { count[i] = top; top = i;//top是用下標表示 } } for(i = 0;i<numVertexs;++i) { if(top == -1) cout<<"Have a circle..."<<endl; else { int j = top; top = count[j]; cout<<myv[j].data<<"-->"; EdgeNode *l = myv[j].link; while(l) { int k = l->dest; if(--count[k] == 0)//這裡的--是將l所指出去相連的邊都刪掉。 { count[k] = top; top = k; } l = l->next; } } } } };
#include"graphvec.h"
int main()
{
GrapHVec<char> tp;
tp.InsertVertex('A');
tp.InsertVertex('B');
tp.InsertVertex('C');
tp.InsertVertex('D');
tp.InsertVertex('E');
tp.InsertVertex('F');
tp.InsertEdge('A','B');
tp.InsertEdge('A','C');
tp.InsertEdge('A','D');
tp.InsertEdge('C','F');
tp.InsertEdge('D','F');
tp.InsertEdge('D','B');
tp.InsertEdge('E','C');
tp.InsertEdge('E','F');
tp.showVecGrap();
cout<<"========================="<<endl;
tp.TopologicalSort();
return 0;
}