在AOV(Activity On Vertex)网(有向无环图)中,用顶点来表示某个活动,用边来表示活动之间的某种先后顺序或者制约关系。
如果有向图中的顶点序列 v1,v2,v3,...,vn 满足:
若从顶点vi到vj有一条路径,那么在此序列中vi必然排在vj之前。
这个序列我们称之为拓扑序列。
对有向图的所有顶点进行构造拓扑序列的过程,就叫做拓扑排序。
另外,对一个有向图进行拓扑排序,结果可能不唯一。
经典的拓扑排序算法思想:
从有向图中选择一个入度为0的顶点输出,然后删除此顶点,并删除以此顶点为尾的边,继续重复此步骤,直到输出全部顶点或者图中不存在入度为0的顶点为止。
当拓扑排序结束后,如果全部顶点都被输出,那么证明这个图是无环图(AOV网),否则即便只有一个顶点没被输出,就说明这个图中存在环路,不是AOV网。
算法的套路比较固定,实现起来也简单:
需要借助一个栈。
int Graph_TopologicalSort(Graph_t* graph)
{
int i = 0;
int k = 0;
GVertex_t* gettop = 0;
int top = 0;
int count = 0;
int v_num = graph->vertex_num;
GVertex_t**stack = NULL;
GVertex_t* pv = NULL;
GEdge_t* pe = NULL;
stack = (GVertex_t**)malloc(sizeof(GVertex_t*)*v_num);
memset(stack, 0, (sizeof(GVertex_t*)*v_num));
__gen_indegree(graph);//统计每个顶点的入度
top = 0;
pv = graph->top_v;
i = 0;
while(pv){//将所有入度为0的顶点入栈
if(pv->in_degree==0){
stack[top++] = pv;
}
pv = pv->next;
}
while(top!=0){
gettop = stack[--top];//出栈,相当于“删除“了此顶点
printf("%s -> ", gettop->name);//用打印来表示“输出“此顶点
count++;//统计输出顶点的个数
pe = gettop->first_edge;
while(pe){//遍历该顶点的所有边,将边的另一个顶点的入度减1(表示已经“删除“了这条边)
pe->tail->in_degree--;
if(pe->tail->in_degree==0){
stack[top++] = pe->tail;//如果这个顶点入度为0则入栈
}
pe = pe->next;
}
}
printf("\n");
if(count < v_num){
printf("There's ring in graph! \n");
return -1;
}
return 0;
}