1、拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在Vi到Vj的路径,那么在排序中Vj出现在Vi的后面。
在讲解拓扑排序之前,我们先介绍一个概念,AOV网:
通常,我们把顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。
2、拓扑排序的步骤:
由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
(1) 选择一个入度为0的顶点并输出之;
(2) 从网中删除此顶点及所有出边。
!!!循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。[2]
3、一个简单的例子理解拓扑排序:
要对这些课程进行排序,当是比较少的课程时,我们可以直接理清楚课程的顺序,但是当课程达到很多时,我们就可以借助图来进行排序,首先我们需要建立一个图,在这里很容易想到,将课程作为图的顶点,在这里我们把边v->w看做v是w的预修课。
根据这个思路建立了如图所示的图:
根据建立的图进行拓扑排序将得到课程的顺序:
c1 c2 c8 c4
c3 c13 c9 c5
c7 c6
c11 c12 c10 c15
c14
通过这个例子,应该对拓扑排序有了更深的理解
4、拓扑排序的代码实现:
bool TopSort( LGraph Graph, Vertex TopOrder[] )
{ /* 对Graph进行拓扑排序, TopOrder[]顺序存储排序后的顶点下标 */
int Indegree[MaxVertexNum], cnt;
Vertex V;
PtrToAdjVNode W;
Queue Q = CreateQueue( Graph->Nv );
/* 初始化Indegree[] */
for (V=0; V<Graph->Nv; V++)
Indegree[V] = 0;//顶点的入度
/* 遍历图,得到Indegree[] */
for (V=0; V<Graph->Nv; V++)
for (W=Graph->G[V].FirstEdge; W; W=W->Next)
Indegree[W->AdjV]++; /* 对有向边<V, W->AdjV>累计终点的入度 */
/* 将所有入度为0的顶点入列 */
for (V=0; V<Graph->Nv; V++)
if ( Indegree[V]==0 )
AddQ(Q, V);
/* 下面进入拓扑排序 */
cnt = 0;
while( !IsEmpty(Q) ){
V = DeleteQ(Q); /* 弹出一个入度为0的顶点 */
TopOrder[cnt++] = V; /* 将之存为结果序列的下一个元素 */
/* 对V的每个邻接点W->AdjV */
for ( W=Graph->G[V].FirstEdge; W; W=W->Next )
if ( --Indegree[W->AdjV] == 0 )/* 若删除V使得W->AdjV入度为0 */
AddQ(Q, W->AdjV); /* 则该顶点入列 */
} /* while结束*/
if ( cnt != Graph->Nv )
return false; /* 说明图中有回路, 返回不成功标志 */
else
return true;
}
关于拓扑排序的另一个应用:路径问题,是基于AOE网络解决的,在这里不做详细讲解,感兴趣的可以去搜一下,实现代码稍改一下就可以实现。