算法 - 图(Graph)- AOV网(Activity On Vertex Nework)- 拓扑排序(Topological Sort)


AOV网(Activity On Vertex Nework)

  • 一项大的工程常被分为多个小的子工程
    子工程之间可能存在一定的先后顺序,即某些子工程必须在其他的一些子工程完成后才能开始
  • 在现代化管理中,人们常用用向图来描述和分析一项工程的计划和实施过程,子工程被称为活动(Activity)
    以顶点为活动、有向边表示活动之间的先后关系,这样的图简称为AOV网
  • 标准的AOV网必须是一个有向无环图(Directed Acyclic Graph,简称DAG)
    在这里插入图片描述

拓扑排序(Topological Sort)

在这里插入图片描述

  • 前驱活动:有向边起点的活动称为终点的前驱活动
    只有当一个活动的前驱全部都完成后,这个活动才能进行
  • 后继活动:有向边终点的活动称为起点的后继活动
  • 什么是拓扑排序?
  1. 将AOV网中所有活动排成一个序列,似的每个活动的前驱活动都排在该活动的前面
  2. 比如上图的拓扑排序结果是:A、B、C、D、E、F或者A、B、D、C、E、F(结果并不一定是唯一的)

拓扑排序 - 思路

  • 可以使用卡恩算法(Kahn于1962年提出)完成拓扑排序
  • 假设L是存放拓扑排序结果的列表
  1. 把所有入度为0的顶点放入L中,然后把这些顶点从图中去掉
  2. 重复操作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);
       }
    }
}
发布了163 篇原创文章 · 获赞 18 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/songzhuo1991/article/details/103071309