拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条从vi到vj的路径,那么在排序中Vj出现在Vi后面。一个简单的求拓扑排序的算法是先找出任意一个没有入边的顶点,然后我们显示该顶点,并将它和它的边一起从图中删除。然后为们对图的其余部分应用同样的方法处理。但是这个方法有一点不好,就是每次都要找入度为0的顶点,这种顶点一般很少,如果图很大的话,每次都遍历一遍就浪费很多时间。升级版是先计算每一个顶点的入度,然后将入度为0的顶点存入队列,操作完之后再更新入度。这样就不用遍历整个图而只需要从出队列操作就可以了。下面是代码,队列的操作在上一篇文章中已经实现,只要把类型改成节点的指针即可。
topSort.h
#ifndef __TOPSORT_H #define __TOPSORT_H struct graph; struct listNode; typedef struct graph *Graph; typedef struct listNode *Vertex; struct graph { int numberOfVertex; Vertex *vertexs; }; struct listNode { int indegree; int vertexnumber; Vertex next; }; void topSort(Graph G); Graph initinalizeAdjList(int listSize); Graph insertAdjList(Graph G,int pos,int a[],int N); #endif
#include "topSort.h" #include "queue.h" void topSort(Graph G) { Queue Q; Vertex V,W; int counter=0; int i; Q=createQueue(); for(i=1;i<=G->numberOfVertex;i++)<span style="white-space:pre"> </span>//找到入度为0的点,将它们入队列 { if(G->vertexs[i]->indegree==0) EnQueue(G->vertexs[i],Q);<span style="white-space:pre"> </span> } while(!isEmpty(Q))<span style="white-space:pre"> </span>//删除该点,然后将其相邻的点入度减1,再重新检测入队列 { V=DeQueue(Q); printf(" %d ",V->vertexnumber); counter++; for(i=1;i<=G->numberOfVertex;i++) { if(isAdj(G->vertexs[i],V)) { if((--G->vertexs[i]->indegree)==0) EnQueue(G->vertexs[i],Q); } } } if(counter!=G->numberOfVertex) { printf("Graph has a cycle\n"); exit(-1); } deleteQueue(Q); } Graph initinalizeAdjList(int listSize)<span style="white-space:pre"> </span>//初始化一个邻接表,就是创建一个指针数组,每个元素只想一个节点 { Graph G; int i; G=(Graph)malloc(sizeof(struct graph)); if(G==NULL) { printf("out of space\n"); exit(-1); } G->numberOfVertex=listSize; G->vertexs=(Vertex*)malloc(sizeof(Vertex)*(listSize+1)); for(i=1;i<=listSize;i++)<span style="white-space:pre"> </span>//这里简单的直接给出节点编号,实际中可以用哈希的方法来获得 { G->vertexs[i]=(Vertex)malloc(sizeof(struct listNode));<span style="white-space:pre"> </span>//初始化节点 G->vertexs[i]->vertexnumber=i; G->vertexs[i]->next=NULL; } return G; } Graph insertAdjList(Graph G,int pos,int a[],int N)<span style="white-space:pre"> </span>//根据给出的数组来给邻接表插入元素 { int j; Vertex v,w; G->vertexs[pos]->indegree=N; w=G->vertexs[pos]; for(j=0;j<N;j++) { v=(Vertex)malloc(sizeof(struct listNode)); v->vertexnumber=a[j]; v->next=NULL; while(w->next) w=w->next; w->next=v; } } int isAdj(Vertex v,Vertex w) //if v adj w<span style="white-space:pre"> </span>判断是不是和目标节点相邻 { Vertex t; t=v->next; while(t) { if(t->vertexnumber==w->vertexnumber) return 1; t=t->next; } return 0; }
#include "queue.h" #include "topSort.h" int main() { Graph G; int i; int a1[]={2,4,3}; int a2[]={4,5}; int a3[]={6}; int a4[]={6,7,3}; int a5[]={4,7}; int a7[]={6}; G=initinalizeAdjList(7); insertAdjList(G,1,a1,3); insertAdjList(G,2,a2,2); insertAdjList(G,3,a3,1); insertAdjList(G,4,a4,3); insertAdjList(G,5,a5,2); insertAdjList(G,6,a5,0); insertAdjList(G,7,a7,1); for(i=1;i<=7;i++) { Vertex v; v=G->vertexs[i]; while(v) { printf(" %d ",v->vertexnumber); v=v->next; } printf("\n"); } topSort(G); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u012000209/article/details/47428639