1、活动
所有的工程或者某种流程都可以分为若干个小的工程或者阶段,我们称这些小的工程或阶段为"活动"。
2、AOV网
在⼀个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系的有向图 称为顶点表示活动的网(Activity On Vertex Network),简称AOV网。
3、拓扑序列
满足若从顶点Vi到Vj有⼀条路径,则在顶点序列中顶点Vi必在顶点Vj之前。则我们称这样的顶点序列为⼀个拓扑序列。
所谓的拓扑排序,其实就是对⼀个有向无环图构造拓扑序列的过程。
4、算法思想
(1) 在有向图中选⼀个没有前驱的顶点且输出之。
(2) 从图中删除该顶点和所有以它为尾的弧。
重复上述两步,直至全部顶点均已输出,或者当前图不存在无前驱的顶点为止,后⼀种情况说明有向图中存在环。
cpp
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
// 拓扑排序函数
// n:顶点数 adj:邻接表 inDegree:每个顶点的入度
bool topologicalSort(int n<int>><int>& inDegree)
{
<int> q;<int> res; // 存储拓扑排序结果
// 步骤1:找到所有没有前驱(入度为0)的顶点,入队
for (int i =<= n; i++)
{
if (inDegree[i] == 0)
{
q.push(i);
}
}
while (!q.empty())
{
// 取出一个无前驱顶点并输出
int cur = q.front();
q.pop();
res.push_back(cur);
// 步骤2:删除该顶点为尾的所有弧,更新后继节点入度
for (int next : adj[cur])
{
inDegree[next]--;
// 后继节点无前驱则入队
if (inDegree[next] == 0)
{
q.push(next);
}
}
}
// 节点数不足说明有环
if (res.size() != n)
{
return false;
}
// 输出拓扑序列< "拓扑排序结果:";
for (int node : res)
{
< " ";
}
cout< endl;
return true;
}
int main()
{
// 6个顶点的有向图测试
int n = 6;<int>> adj(n + 1<int> inDegree(n + 1, 0);
// 构建图的边<int, int>> edges = {{1,2}, {1,3}, {2,4}, {3,4}, {4,5}, {4,6}};
for (auto& e : edges)
{
int u = e.first;
int v = e.second;
adj[u].push_back(v);
inDegree[v]++;
}
// 执行拓扑排序并判环
if (!topologicalSort(n, adj, inDegree))
{
cout< "有向图存在环路,无法完成拓扑排序< endl;
}
return 0;
}
拓扑排序在实际的⽣产中很常见,最经典的例子就是课程表,当然还可以进行代码的依赖关系处理等等。