拓扑排序讲解java_java拓扑排序实例源码介绍

java拓扑排序实例源码介绍。当每个任务有前后置关系时,需要找到一种满足前后置关系的路线,将任务完成。

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

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

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

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

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

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

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

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

关键API:

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

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

main:提供简单的测试。

代码如下:

1

1453345e2d90d3de45dc0fbf57f4f8c2.gifclass Vertex {    //图中的节点

2

6ccce377c8dda871f5607f209c56c00a.gif    private Object value;

3

8903c176ec97a013420bbd3b720b6130.gif    Vertex(Object value) {

4

6ccce377c8dda871f5607f209c56c00a.gif        this.value = value;

5

54481098032e28d7d4654589d5016b5f.gif    }

6

8903c176ec97a013420bbd3b720b6130.gif    Object value() { return value; }

7

8903c176ec97a013420bbd3b720b6130.gif    @Override public String toString() { return ”" + value; }

8

93a307cd5415d9f49469692045120a10.gif}

9

d4d1619462e5d986eb159811f3412d06.gif

10

1453345e2d90d3de45dc0fbf57f4f8c2.gifclass Topology {    //用邻接矩阵法表示的图

11

6ccce377c8dda871f5607f209c56c00a.gif    private Vertex[] vertexs;

12

6ccce377c8dda871f5607f209c56c00a.gif    private Object[][] adjMat;    //记载是否联通

13

6ccce377c8dda871f5607f209c56c00a.gif    private int length = 0;

14

6ccce377c8dda871f5607f209c56c00a.gif    private static Object CONN = new Object();    //标致是否联通

15

6ccce377c8dda871f5607f209c56c00a.gif

16

8903c176ec97a013420bbd3b720b6130.gif    Topology(int size) {

17

6ccce377c8dda871f5607f209c56c00a.gif        vertexs = new Vertex[size];

18

6ccce377c8dda871f5607f209c56c00a.gif        adjMat = new Object[size][size];

19

54481098032e28d7d4654589d5016b5f.gif    }

20

6ccce377c8dda871f5607f209c56c00a.gif

21

8903c176ec97a013420bbd3b720b6130.gif    void add(Object value) {

22

6ccce377c8dda871f5607f209c56c00a.gif        assert length <= vertexs.length;

23

6ccce377c8dda871f5607f209c56c00a.gif        vertexs[length++] = new Vertex(value);

24

54481098032e28d7d4654589d5016b5f.gif    }

25

6ccce377c8dda871f5607f209c56c00a.gif

26

8903c176ec97a013420bbd3b720b6130.gif    void connect(int from, int to) {

27

6ccce377c8dda871f5607f209c56c00a.gif        assert from 

28

6ccce377c8dda871f5607f209c56c00a.gif        assert to 

29

6ccce377c8dda871f5607f209c56c00a.gif        adjMat[from][to] = CONN;    //标志联通

30

54481098032e28d7d4654589d5016b5f.gif    }

31

6ccce377c8dda871f5607f209c56c00a.gif

32

8903c176ec97a013420bbd3b720b6130.gif    void remove(int index) {    //移除指定的顶点

33

6ccce377c8dda871f5607f209c56c00a.gif        remove(vertexs,index);    //在顶点数组中删除指定位置的下标

34

6ccce377c8dda871f5607f209c56c00a.gif        for(Object[] bs: adjMat) remove(bs,index);    //邻接矩阵中删除指定的列

35

6ccce377c8dda871f5607f209c56c00a.gif        remove(adjMat,index);    //在邻接矩阵中删除指定的行

36

6ccce377c8dda871f5607f209c56c00a.gif        length–;

37

54481098032e28d7d4654589d5016b5f.gif    }

38

6ccce377c8dda871f5607f209c56c00a.gif

39

8903c176ec97a013420bbd3b720b6130.gif    private void remove(Object[] a, int index) {    //在数组中移除指定的元素,后面的元素补上空位

40

6ccce377c8dda871f5607f209c56c00a.gif        for(int i=index; i

41

54481098032e28d7d4654589d5016b5f.gif    }

42

6ccce377c8dda871f5607f209c56c00a.gif

43

8903c176ec97a013420bbd3b720b6130.gif    int noNext() {    //寻找没有后继的节点

44

6ccce377c8dda871f5607f209c56c00a.gif        int result = -1;

45

6ccce377c8dda871f5607f209c56c00a.gifOUT:

46

8903c176ec97a013420bbd3b720b6130.gif        for(int i=0; i

47

8903c176ec97a013420bbd3b720b6130.gif            for(int j=0; j

48

6ccce377c8dda871f5607f209c56c00a.gif                if(adjMat[i][j] == CONN)continue OUT;    //如果有后继则从外循环继续寻找

49

54481098032e28d7d4654589d5016b5f.gif            }

50

6ccce377c8dda871f5607f209c56c00a.gif            return i;    //如果没有与任何节点相连,则返回该节点下标

51

54481098032e28d7d4654589d5016b5f.gif        }

52

6ccce377c8dda871f5607f209c56c00a.gif        return -1;    //否则返回-1

53

54481098032e28d7d4654589d5016b5f.gif    }

54

6ccce377c8dda871f5607f209c56c00a.gif

55

8903c176ec97a013420bbd3b720b6130.gif    Object[] topo() {

56

6ccce377c8dda871f5607f209c56c00a.gif        Object[] result = new Object[length];    //准备结果数组

57

6ccce377c8dda871f5607f209c56c00a.gif        int index;

58

6ccce377c8dda871f5607f209c56c00a.gif        int pos = length;

59

8903c176ec97a013420bbd3b720b6130.gif        while(length > 0) {

60

6ccce377c8dda871f5607f209c56c00a.gif            index = noNext();    //找到第一个没有后继的节点

61

6ccce377c8dda871f5607f209c56c00a.gif            assert index != -1 : ”图中存在环”;

62

6ccce377c8dda871f5607f209c56c00a.gif            result[--pos] = vertexs[index]; //放入结果中

63

6ccce377c8dda871f5607f209c56c00a.gif            remove(index);    //从图中把它删除

64

54481098032e28d7d4654589d5016b5f.gif        }

65

6ccce377c8dda871f5607f209c56c00a.gif        return result;

66

54481098032e28d7d4654589d5016b5f.gif    }

67

6ccce377c8dda871f5607f209c56c00a.gif

68

8903c176ec97a013420bbd3b720b6130.gif    public static void main(String[] args) {

69

6ccce377c8dda871f5607f209c56c00a.gif        Topology g = new Topology(20);

70

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘a’);

71

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘b’);

72

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘c’);

73

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘d’);

74

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘e’);

75

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘f’);

76

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘g’);

77

6ccce377c8dda871f5607f209c56c00a.gif        g.add(‘h’);

78

6ccce377c8dda871f5607f209c56c00a.gif

79

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(0,3);

80

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(0,4);

81

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(1,4);

82

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(2,5);

83

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(3,6);

84

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(4,6);

85

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(5,7);

86

6ccce377c8dda871f5607f209c56c00a.gif        g.connect(6,7);

87

6ccce377c8dda871f5607f209c56c00a.gif

88

6ccce377c8dda871f5607f209c56c00a.gif        for(Object o: g.topo()) System.out.print(o + ” ”);

89

6ccce377c8dda871f5607f209c56c00a.gif        System.out.println();

90

54481098032e28d7d4654589d5016b5f.gif    }

91

93a307cd5415d9f49469692045120a10.gif}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值