AOV网(Activity On Vertex Nework)
- 一项大的工程常被分为多个小的子工程
子工程之间可能存在一定的先后顺序,即某些子工程必须在其他的一些子工程完成后才能开始
- 在现代化管理中,人们常用用向图来描述和分析一项工程的计划和实施过程,子工程被称为活动(Activity)
以顶点为活动、有向边表示活动之间的先后关系,这样的图简称为AOV网
- 标准的AOV网必须是一个有向无环图(Directed Acyclic Graph,简称DAG)
拓扑排序(Topological Sort)
- 前驱活动:有向边起点的活动称为终点的前驱活动
只有当一个活动的前驱全部都完成后,这个活动才能进行
- 后继活动:有向边终点的活动称为起点的后继活动
- 什么是拓扑排序?
- 将AOV网中所有活动排成一个序列,似的每个活动的前驱活动都排在该活动的前面
- 比如上图的拓扑排序结果是:A、B、C、D、E、F或者A、B、D、C、E、F(结果并不一定是唯一的)
拓扑排序 - 思路
- 可以使用卡恩算法(Kahn于1962年提出)完成拓扑排序
- 假设L是存放拓扑排序结果的列表
- 把所有入度为0的顶点放入L中,然后把这些顶点从图中去掉
- 重复操作1,知道找不到入度为0的顶点
- 如果此时L中的元素个数和顶点总数相同,说明拓扑排序完成
- 如果此时L中的元素个数少于顶点总数,说明原图中存在环,无法进行拓扑排序
拓扑排序 - 实现
List<V> list = new ArrayList<>();
Queue<Vertex<V, E>> queue = new LinkedList<>();
Map<Vertex<V, E>, Integer> ins = new HashMap<>();
vertices.forEach((V key, Vertex<V, E> vertex) -> {
Integer in = vertex.inEdges.size();
if (in == 0) {
queue.offer(vertex);
} else {
ins.put(vertex, in);
}
});
while (!queue.isEmpty()) {
Vertex<V, E> vertex = queue.poll();
list.add(vertex.value);
for (Edge<V, E> edge : vertex.outEdges) {
Integer in = ins.get(edge.to) - 1;
if (in == 0) {
queue.offer(edge.to);
} else {
ins.put(edge.to, in);
}
}
}