【图论】拓扑排序

AOV网

  • 在日常生活中,一个大工程可以看作是由若干个子工程组成的集合,这些子工程(活动)之间必定存在一定的先后关系,即某些子工程(活动)必须在其他一些子工程完成之后才能开始。我们可以用有向图来形象地表示这些子工程之间的先后关系,子工程为顶点,子工程之间的先后关系为有向边,这种有向图称为“顶点活动网络”,又称AOV网络。
  • 一个AOV网络必定是一个有向无环图,即不应该带有回路,否则会出现先后关系的自相矛盾。

拓扑排序算法

    • 拓扑排序算法只适用于AOV网(有向无环图)
    • 把AOV网络中的所有活动排列成一个序列,使得每个活动的所有前驱活动都排在该活动的前面,这个过程就成为“拓扑排序”,所得到的活动序列称为“拓扑序列”。
    • 一个AOV网络的拓扑排序并不是唯一的。没有前后关系的活动,不同的遍历方式可能会产生不同的拓扑顺序。
  • 算法思想:
    • 选择一个入度为0的顶点m,入度为0,说明是任务的起始点
    • 将顶点m删除,并删除与m相连的边
    • 继续寻找一个入度为0的点,重复上面的操作
    • 直到不存在入度为0的点,完成
    • 如果输出的顶点数小于AOV网络中的定点数,则说明这个活动图存在回路
  • 算法实现:
    • 输入格式:
      • 首先输入N,表示有多少个活动
      • 然后第i行代表第i个活动指向的活动
    • 算法具体操作:
      • 在输入数据的时候,记录下每个点的入度和出度。当入度为零的点删除时,出度方便操作其他入度要减一的点。
      • matrix矩阵存放的不是常规的图的信息,matrix[i][j]=k,表示第i个点连接的第j个位置上的点是k;所以矩阵密度稀疏
      • 这样做,方便做入度--操作
  • 实现的通俗表达
    • 根据入度信息,找出入度为0的点(可能有多个),存放到一个数组里。然后迭代取出数组里的一个点,接着根据这个点的出度信息,修改matrix中那些点的入度信息,然后再遍历入度表,将度为0的点加入到数组里。不断的从数组里取,然后再添加新的,直到已经输出了所有节点。
 1     int n;
 2     int matrix[][];// matrix[i][j] = k 代表和i点相连的第j个点是k
 3     int inDegree[]; // 每个点的入度
 4     int outDegree[]; // 每个点的出度,帮组定位每个点连接了几个元素
 5     int visit[];//临时存放出度为入的点
 6     int p;
 7     int num; // 记录输出了多少个点
 8 
 9     public void topSort() {
10         for (int i = 0; i < n; i++) {
11             if (inDegree[i] == 0) {
12                 visit[++p] = i;
13             }
14         }
15         do {
16             int tmp = visit[p]; // 取出最近一个入度为0的点
17             System.out.println(tmp);// 输出
18 
19             num++; // 找的了一个元素
20             p--; //继续遍历出度为0的点做准备
21 
22             for (int i = 0; i <= outDegree[tmp]; i++) {
23                 inDegree[matrix[tmp][i]]--; // 和tmp相邻的点入度--
24                 if (inDegree[matrix[tmp][i]] == 0) {
25                     visit[++p] = matrix[tmp][i];
26                 }
27             }
28         } while (num != n);
29     }
拓扑排序Java

代码实现并不完整,inDegree和outDegree需要在数据输入的时候进行计算,并且matrix存储的内容所表示的意义也和其他的图的存储方式有所区别。

posted @ 2018-06-24 00:54  buliang  阅读(838)  评论(0编辑  收藏  举报