两种拓扑排序方法: dfs和bfs的。
先看bfs, 核心在于维护节点的剩余入度(这个词是自造的,因为入度不为0的节点的全部前继节点都被遍历过之后,该节点入度就变为0了)
每次搜索都把 剩余入度为0的节点 添加进拓扑序列末尾。 因为这个时候,他的前继节点已经都在拓扑序列中了。
剩余入度怎么维护?
首先搜索的起始点必定是入度为0的点,其他节点的剩余入度初始化为入度值。
每当节点A的剩余入度变为0的时候,A的所有后继节点剩余入度减一。 因为A的剩余入度为0,说明不可能再从A进入他的后继了。
queue<int> q;
vector<int> topoSeq;
for(int i=0; i<n; i++)
{
if( predecessor[i] == 0) //入度为0
{
q.push(i);
}
}
int cur;
while( !q.empty())
{
cur = q.front();
topoSeq.push_back( cur ); //队列头 必然是入度为0的
for (int i=0; i<n; i++) // 遍历后继
{
if( G[cur][i] < infinity )
{
--predecessor[i]; //节点i的前节点cur入度是0,已经不可能经过 cur再进入节点i了,所以节点i的入读需要减一
if (predecessor[i] == 0) // 节点i的最后一个未入口也访问完了,i已经没有前节点
{
q.push(i);
}
}
}
q.pop();
}
BFS的做法是从起点到终点构造出 拓扑序列的。
而DFS的做法,因为要到图的末尾才返回,那么构造拓扑序列则是从后往前的。
topologySort( topoSeq, Vertex, visited[])
{
visited[ v ] = true;
for (i=0; i< successor[v].size(); i++)
{
w = successor[v][ i ];
if( isvisited[w] == true ) continue;
topologySort( topoSeq, w, visited );
}
topoSeq.insertHead( v );
}
for( v=0; v<VertexCount; v++)
{
if ( visited[ v ] == false) topologySort(topoSeq, v, visited );
}