图(有向图)的应用——拓扑排序

来源:互联网 发布:sql语句统计数量 编辑:程序博客网 时间:2024/06/08 14:34

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);//Aint v2 = GetVerticespos(x2);//Bif(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;}




0 0
原创粉丝点击