图-拓扑排序

当每个任务有前后置关系时,需要找到一种满足前后置关系的路线,将任务完成。

如果将每个任务看成一个节点,任务之间的前后置关系表示为有向图时,这种路线顺序叫做为图进行拓扑排序。也叫关键路径分析。

这里的图用邻接矩阵法表示,算法的关键是:

1 找到一个没有后继的顶点

2 在图中删除它,放入结果数组中

3 重复 步骤 1 ,步骤 2 直到图中没有多余的节点。

如果图中出现环装结构,则算法无法进行,因为此时任务之间循环成为前置。

关于邻接矩阵法请参见:Graph 图-邻接表法。

要注意的是:满足前后置关系的路径可能不止一条。这里仅仅得到其中的一条。

关键API:

   int noNext():返回没有后继的节点的下标。

   remove(int index):删除指定下标的节点,同时在邻接矩阵中删除相对应的行与列。

   main:提供简单的测试。

代码如下:

 

 1
《图-拓扑排序》
class
 Vertex 
{    //图中的节点
 2《图-拓扑排序》    private Object value;
 3《图-拓扑排序》    Vertex(Object value) {
 4《图-拓扑排序》        this.value = value;
 5《图-拓扑排序》    }

 6《图-拓扑排序》    Object value() return value; }
 7《图-拓扑排序》    @Override public String toString() return “” + value; }
 8《图-拓扑排序》}



 9
《图-拓扑排序》

10
《图-拓扑排序》
class
 Topology 
{    //用邻接矩阵法表示的图
11《图-拓扑排序》    private Vertex[] vertexs;
12《图-拓扑排序》    private Object[][] adjMat;    //记载是否联通    
13《图-拓扑排序》    private int length = 0;
14《图-拓扑排序》    private static Object CONN = new Object();    //标致是否联通
15《图-拓扑排序》
16《图-拓扑排序》    Topology(int size) {
17《图-拓扑排序》        vertexs = new Vertex[size];
18《图-拓扑排序》        adjMat = new Object[size][size];
19《图-拓扑排序》    }

20《图-拓扑排序》
21《图-拓扑排序》    void add(Object value) {
22《图-拓扑排序》        assert length <= vertexs.length;
23《图-拓扑排序》        vertexs[length++] = new Vertex(value);
24《图-拓扑排序》    }

25《图-拓扑排序》
26《图-拓扑排序》    void connect(int from, int to) {
27《图-拓扑排序》        assert from < length;
28《图-拓扑排序》        assert to < length;
29《图-拓扑排序》        adjMat[from][to] = CONN;    //标志联通
30《图-拓扑排序》    }

31《图-拓扑排序》
32《图-拓扑排序》    void remove(int index) {    //移除指定的顶点
33《图-拓扑排序》        remove(vertexs,index);    //在顶点数组中删除指定位置的下标
34《图-拓扑排序》        for(Object[] bs: adjMat) remove(bs,index);    //邻接矩阵中删除指定的列
35《图-拓扑排序》        remove(adjMat,index);    //在邻接矩阵中删除指定的行
36《图-拓扑排序》        length–;
37《图-拓扑排序》    }

38《图-拓扑排序》
39《图-拓扑排序》    private void remove(Object[] a, int index) {    //在数组中移除指定的元素,后面的元素补上空位
40《图-拓扑排序》        for(int i=index; i<length-1; i++) a[i] = a[i+1];
41《图-拓扑排序》    }

42《图-拓扑排序》
43《图-拓扑排序》    int noNext() {    //寻找没有后继的节点
44《图-拓扑排序》        int result = -1;
45《图-拓扑排序》OUT:
46《图-拓扑排序》        for(int i=0; i<length; i++) {
47《图-拓扑排序》            for(int j=0; j<length; j++) {
48《图-拓扑排序》                if(adjMat[i][j] == CONN)continue OUT;    //如果有后继则从外循环继续寻找
49《图-拓扑排序》            }

50《图-拓扑排序》            return i;    //如果没有与任何节点相连,则返回该节点下标
51《图-拓扑排序》        }

52《图-拓扑排序》        return -1;    //否则返回-1
53《图-拓扑排序》    }

54《图-拓扑排序》
55《图-拓扑排序》    Object[] topo() {
56《图-拓扑排序》        Object[] result = new Object[length];    //准备结果数组
57《图-拓扑排序》        int index;
58《图-拓扑排序》        int pos = length;
59《图-拓扑排序》        while(length > 0) {
60《图-拓扑排序》            index = noNext();    //找到第一个没有后继的节点    
61《图-拓扑排序》            assert index != -1 : “图中存在环”;
62《图-拓扑排序》            result[–pos] = vertexs[index]; //放入结果中
63《图-拓扑排序》            remove(index);    //从图中把它删除
64《图-拓扑排序》        }

65《图-拓扑排序》        return result;
66《图-拓扑排序》    }

67《图-拓扑排序》
68《图-拓扑排序》    public static void main(String[] args) {
69《图-拓扑排序》        Topology g = new Topology(20);
70《图-拓扑排序》        g.add(‘a’);
71《图-拓扑排序》        g.add(‘b’);
72《图-拓扑排序》        g.add(‘c’);
73《图-拓扑排序》        g.add(‘d’);
74《图-拓扑排序》        g.add(‘e’);
75《图-拓扑排序》        g.add(‘f’);
76《图-拓扑排序》        g.add(‘g’);
77《图-拓扑排序》        g.add(‘h’);
78《图-拓扑排序》
79《图-拓扑排序》        g.connect(0,3);
80《图-拓扑排序》        g.connect(0,4);
81《图-拓扑排序》        g.connect(1,4);
82《图-拓扑排序》        g.connect(2,5);
83《图-拓扑排序》        g.connect(3,6);
84《图-拓扑排序》        g.connect(4,6);
85《图-拓扑排序》        g.connect(5,7);
86《图-拓扑排序》        g.connect(6,7);
87《图-拓扑排序》
88《图-拓扑排序》        for(Object o: g.topo()) System.out.print(o + ” “);
89《图-拓扑排序》        System.out.println();
90《图-拓扑排序》    }

91《图-拓扑排序》}

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/xiyf2046/article/details/12708825
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞