拓扑排序,对有向无圈图的顶点的一种排序,如果图中存在一条从顶点vi到vj的路径,那么在排序中vj必须出现vi后面,并且顶点都只出现一次。
度是指一个顶点所有与之相关联的边的数量。 入度是指以该顶点为终点的边的数量。 出度是指以该顶点为起点的边的数量。
在一个有向无圈图中,列出所有顶点的入度,找出一个入度为0的顶点,编号为1,然后删除图中所有以1号为起点的边。然后再找出一个入度为0的顶点,编号为2,重复上述步骤至图中没有顶点。 这个过程中有时会出现多个入度为0的顶点,这时算法可以继续下去,拓扑排序只要不违反上面两条原则就可以执行。 算法执行完毕,但是图中还有顶点没有输出,但是再也找不到入度为0的顶点了,这说明图中有环。(这不就是证明图中存在环么。。。)
实现是这样的,将所有还没有分配拓扑编号的入度为0的顶点放在队列中,在随后的执行过程中,队列不空,就推出队列的顶点,并编号它,然后将所有与它邻接的顶点的入度减1,只要某个顶点的入度减为0,就把他加入队列中。当最后实际编号的顶点数小于图的顶点数,就报告这个图有环。
void TopSort(Graph G,int TopNum[],int indegree[]) //图,拓扑排序结果,入度。 { Queue Q; int count=0; //编号计数 Vertex v,w; //顶点下标 AdjVNode M; //顶点
Q=MakeQueue(G->Nv); MakeEmpty(Q); for(i=0;i<G->Nv;i++) { if (indegree[i]==0) { Enqueue(i,Q); } } while(!IsEmpty(Q)) { v=Dequeue(Q); TopNum[v]=++count; //分配编号 for(M=G->G[v].FirstEdge->Next;;M=M->Next) //G-G[]是邻接表。 { indegree[M->Adjv]--; //M->Adjv是这个邻接点的下标 if (indegree[M->Adjv]==0) { Enqueue(M->Adjv,Q); //入度减为0的顶点进入队列 } } } if(count!=G->Nv) { printf("Graph has a cycle"); } DisposeQueue(Q); //删掉队列.}