-
拓扑排序
-
在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列。必须满足:
- 每个顶点出现且只出现一次。
- 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。
-
直接上例子:
-
上图就是一个有向无环图的拓扑排序的过程:输出{1,2,4,3,5}
- 从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。
- 从图中删除该顶点和所有以它为起点的有向边。
- 重复 1 和 2 直到当前的 DAG 图为空。
- 若当前图中不存在无前驱的顶点。则说明有向图中必然存在环。
-
一个有向无环图可能会有多个拓扑排序的序列结果。
-
-
拓扑排序的代码实现
-
先将所有入度为0的顶点入队;
-
while循环中出队出一个顶点并输出;
-
将这个顶点指向的顶点的度减1,入度减到0的顶点入队;
-
栈空后,如果输出的节点数少于所有节点数,则有环路。
bool Graph::topological_sort() { for(int i=0; i<V; ++i) if(indegree[i] == 0) q.push(i); // 将所有入度为0的顶点入队 int count = 0; // 计数,记录当前已经输出的顶点数 while(!q.empty()) { int v = q.front(); // 从队列中取出一个顶点 q.pop(); cout << v << " "; // 输出该顶点 ++count; // 将所有v指向的顶点的入度减1,并将入度减为0的顶点入栈 list<int>::iterator beg = adj[v].begin(); for( ; beg!=adj[v].end(); ++beg) if(!(--indegree[*beg])) q.push(*beg); // 若入度为0,则入栈 } if(count < V) return false; // 没有输出全部顶点,有向图中有回路 else return true; // 拓扑排序成功 }
- 还有一种DFS的方法没有仔细研究。
-
-
拓扑排序的应用
-
拓扑排序解决活动顺序问题:
- 拓扑排序对应施工的流程图具有特别重要的作用,它可以决定哪些子工程必须要先执行,哪些子工程要在某些工程执行后才可以执行。
- 通常,我们把顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。如果这个图中有环路,则整个活动无法完成。
-
Leetcode #207 课程表:
课程选修之间的先后关系用一个图来表示,如果有环路则无法完成。就利用拓扑排序即可。
Leetcode #210 课程表:也是一样,只不过是还需要把序列输出而已。
-