20230406 8.2. 拓扑排序

发布时间 2023-06-21 16:27:27作者: 流星<。)#)))≦

概念

  • 拓扑序:如果图中从V到W有一条有向路径,则V一定排在W之前。满足此条件的顶点序列称为一个拓扑序
  • 获得一个拓扑序的过程就是拓扑排序
  • AOV (Activity On Vertex) 如果有合理的拓扑序,则必定是 有向无环图(Directed Acyclic Graph, DAG)
void TopSort()
{ 
    for ( 图中每个顶点 V )
    if ( Indegree[V]==0 )
        Enqueue( V, Q );
    while ( !IsEmpty(Q) ) {
        V = Dequeue( Q );
        输出V,或者记录V的输出序号; cnt++;
        for ( V 的每个邻接点 W )
        if ( ––Indegree[W]==0 )
        Enqueue( W, Q );
    }
    if ( cnt != |V| )
        Error( “图中有回路” );
}
  • 此算法可以用来检测有向图是否 DAG(有向无环图)
  • T = O( |V| + |E| )

例题:计算机专业排课

AOV (Activity On Vertex) 网络

课程号 课程名称 预修课程
C1 程序设计基础
C2 离散数学
C3 数据结构 C1, C2
C4 微积分(一)
C5 微积分(二) C4
C6 线性代数 C5
C7 算法分析与设计 C3
C8 逻辑与计算机设计基础
C9 计算机组成 C8
C10 操作系统 C7, C9
C11 编译原理 C7, C9
C12 数据库 C7
C13 计算理论 C2
C14 计算机网络 C10
C15 数值分析 C6

例题:计算机专业排课

/**
    * 拓扑排序
    */
public void topSort() {
    // 计算每个节点的入度
    int[] inDegress = new int[size];
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            if (edges[i][j] == 1) {
                inDegress[j]++;
            }
        }
    }

    // 将入度为0的节点加入队列
    Queue<Integer> queue = new LinkedList<>();
    for (int i = 0; i < inDegress.length; i++) {
        if (inDegress[i] == 0) {
            queue.offer(i);
        }
    }

    List<Integer> retList = ListUtil.toList();
    while (!queue.isEmpty()) {
        Integer v = queue.poll();
        retList.add(v);

        // 将临接点的入度减一,如果入度为0,加入队列
        for (int i = 0; i < size; i++) {
            if (edges[v][i] == 1 && inDegress[i] > 0) {
                if (--inDegress[i] == 0) {
                    queue.offer(i);
                }
            }
        }
    }

    if (retList.size() != size) {
        throw new RuntimeException("图中有回路");
    }
    Console.log(retList);


}

关键路径问题

  • AOE (Activity On Edge) 网络
  • 一般用于安排项目的工序

项目的工序

关键路径问题