拓扑排序是对有向无圈图的顶点的一种排序,它使得如果存在一条从vi到vj的路径,那么在排序中vj出现在vi的后面。显然,如果图中存在圈,那么拓扑排序是不可能完成的,因为对于圈上的两个顶点v和w,v先于w的同时w先于v,是矛盾的。
一个简单的拓扑排序的算法:
void
Topsort(Gragh G)
{
int Counter;
Vertex V,W;
for(Counter = 0; Counter < NumVertex; Counter++)
{
V = FindNewVertexOfIndegreeZero(); //寻找一个尚未被分配拓扑编号的入度为0的顶点
if(V == NotAVertex)
{
Error("Gragh has a cycle");
break;
}
TopNum[V] = Counter;
for each W adjacent to V
Indegree[W]--;
}
}
一个简单的求拓扑排序的算法是先找出任意一个没有入边的顶点,然后我们显示出该顶点,并将它和它的边一同从图中删除。
我们把顶点v的入度定义为边(u,v)的条数,计算图中所有顶点的入度,设Indegree数组被初始化且图被读入一个邻接表中。
但是这种方法虽然简单,也很耗时,因为FindNewVertexOfIndegreeZero()是对Indegree数组顺序扫描。
另一种更好的办法是将所有(未分配拓扑编号)入度为0的顶点放在一个特殊的盒子中而避免了一遍又一遍的扫描。
我们可以使用一个队列,首先对每一个顶点计算他的入度。然后将所有入度为0的顶点放入一个初始的空的队列中。
当队列不为空时,删除一个项v,并将与其邻接的所有顶点的入度减1.只要一个顶点的入度降为0,就把该顶点放入
队列中。
伪代码实现如下
void
Topsort( Gragh G)
{
Queue Q;
int Counter = 0;
Vertex V,W;
Q = CreateQueue(NumVertex); MakeEmpty(Q);
for each vertex V
if(Indegree[V] == 0)
EnQueue(V, Q);
while( !Empty(Q))
{
V = DeQueue(Q);
TopNum[V] = ++Counter; //Assign next number
for each W adjacent to V
if( --Indegree[W] == 0)
EnQueue(W, Q);
}
if(Countrt != NumVertex)
Error("Gragh has a cycle");
DisposeQueue(Q); //free the memory
}
}