拓扑排序:对DAG的一种排序方式,要求若存在一条从到
的路径,那么在排序中
出现在
后面
特点:
1.不能有圈,否则不可能拓扑排序
2.拓扑排序不是唯一的
入度:顶点v的入度是,边的条数,拓扑排序显然从入度为0的顶点开始
一个简单的思想是,找一个入度为0的顶点,打印,将它和边删除,继续找下一个,代码如下:
#ifdef persudo_code
/* 有向图拓扑排序,简单方法,时间O(V^2) */
void TopSort(Graph G)
{
int Counter;
Vertex V, W;
for (Counter = 0; Counter < NumVertex; Counter++)
{
/* 找一个入度为0的顶点 */
V = FindNewVertexOfIndreeZero();
if (NotAVertex == V)
break;
/* 计数,用于打印 */
TopNum[V] = Counter;
/* 所有邻接顶点入度要减少 */
for each W adjacent to V
Indegree[W]--;
}
if (Counter != NumVertex)
error("Graph has a cycle");
}
#endif
这个算法每次都扫描Indegree数组,浪费时间,使用队列改进,代码如下:
/* 使用队列改进的拓扑排序,时间O(V+E) */
void TopSort(Graph G)
{
Queue Q;
int Counter = 0;
Vertex V, W;
/* 创建一个队列 */
Q = CreateQueue(NumVertex);
MakeEmpty(Q);
/* 将所有入度为0的顶点入队列,时间O(V) */
for each vertex V
if (0 == Indegree[V])
Enqueue(V, Q);
/* 循环读取队列,时间O(V+E) */
while (!IsEmpty(Q))
{
/* 每个顶点出队一次,时间一共是O(V) */
V = Dequeue(Q);
TopNum[V] = ++Counter;
/* 每条边处理一次,时间一共是O(E) */
for each W adjacent to V
if (--Indegree[W] == 0)
Enqueue(W, Q);
}
if (Counter != NumVertex)
error("Graph has a cycle");
DisposeQueue(Q);
}