在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Active On Vertex Network)

AOV网不能存在回路

拓扑排序含义

设G=(V,E)是一个具有n个顶点的有向图,V中的顶点序列V1,V2,....,Vn满足若从顶点Vi到Vj有一条路径,则在顶点序列中顶点Vi必在顶点Vj之前。则我们称这样的顶点序列为一个拓扑排序。

所谓拓扑排序,其实就是对一个有向图构造拓扑序列的过程

拓扑排序算法(TopologicalSort)

对AOV网进行拓扑排序的方法和步骤如下:

1.从AOV网中选择一个没有前驱的顶点(该顶点的入度为0)并且输出它;

2.从网中删去该顶点,并且删去从该顶点发出的全部有向边;

3.重复上述两步,直到剩余网中不再存在没有前驱的顶点为止。



代码示例图:

java 拓扑图技术_图

java 拓扑图技术_拓扑排序_02

代码:

public class Topological {
    
    /**
     * 顶点数组
     */
    private List<VertexNode> vexList;
    
    /**
     * 创建图(邻接表)
     */
    public void createGraph(){
        //v0
        VertexNode v0 = new VertexNode(0, 0, null);
        
        EdgeNode v0e0 = new EdgeNode(11, 0, null);
        EdgeNode v0e1 = new EdgeNode(5, 0, null);
        EdgeNode v0e2 = new EdgeNode(4, 0, null);
        
        v0.setFirstEdge(v0e0);
        v0e0.setNext(v0e1);
        v0e1.setNext(v0e2);
        
        //v1
        VertexNode v1 = new VertexNode(0, 1, null);
        
        EdgeNode v1e0 = new EdgeNode(8, 0, null);
        EdgeNode v1e1 = new EdgeNode(4, 0, null);
        EdgeNode v1e2 = new EdgeNode(2, 0, null);
        
        v1.setFirstEdge(v1e0);
        v1e0.setNext(v1e1);
        v1e1.setNext(v1e2);
        
        //v2
        VertexNode v2 = new VertexNode(2, 2, null);
        
        EdgeNode v2e0 = new EdgeNode(9, 0, null);
        EdgeNode v2e1 = new EdgeNode(6, 0, null);
        EdgeNode v2e2 = new EdgeNode(5, 0, null);
        
        v2.setFirstEdge(v2e0);
        v2e0.setNext(v2e1);
        v2e1.setNext(v2e2);
        
        //v3
        VertexNode v3 = new VertexNode(0, 3, null);
        
        EdgeNode v3e0 = new EdgeNode(13, 0, null);
        EdgeNode v3e1 = new EdgeNode(2, 0, null);
        
        v3.setFirstEdge(v3e0);
        v3e0.setNext(v3e1);
        
        //v4
        VertexNode v4 = new VertexNode(2, 4, null);
        
        EdgeNode v4e0 = new EdgeNode(7, 0, null);
        
        v4.setFirstEdge(v4e0);
        
        //v5
        VertexNode v5 = new VertexNode(3, 5, null);
        
        EdgeNode v5e0 = new EdgeNode(12, 0, null);
        EdgeNode v5e1 = new EdgeNode(8, 0, null);
        
        v5.setFirstEdge(v5e0);
        v5e0.setNext(v5e1);
        
        //v6
        VertexNode v6 = new VertexNode(1, 6, null);
        
        EdgeNode v6e0 = new EdgeNode(5, 0, null);
        
        v6.setFirstEdge(v6e0);
        
        //v7
        VertexNode v7 = new VertexNode(2, 7, null);
        
        //v8
        VertexNode v8 = new VertexNode(2, 8, null);
        
        EdgeNode v8e0 = new EdgeNode(7, 0, null);
        
        v8.setFirstEdge(v8e0);
        
        //v9 入度应为2,不是图片中的1(图片中已经改过来了)
        VertexNode v9 = new VertexNode(2, 9, null);
        
        EdgeNode v9e0 = new EdgeNode(11, 0, null);
        EdgeNode v9e1 = new EdgeNode(10, 0, null);
        
        v9.setFirstEdge(v9e0);
        v9e0.setNext(v9e1);
        
        //v10
        VertexNode v10 = new VertexNode(1, 10, null);
        
        EdgeNode v10e0 = new EdgeNode(13, 0, null);
        
        v10.setFirstEdge(v10e0);
        
        //v11
        VertexNode v11 = new VertexNode(2, 11, null);
        
        //v12
        VertexNode v12 = new VertexNode(1, 12, null);
        
        EdgeNode v12e0 = new EdgeNode(9, 0, null);
        
        v12.setFirstEdge(v12e0);
        
        //v13
        VertexNode v13 = new VertexNode(2, 13, null);
        
        vexList = new ArrayList<>();
        vexList.add(v0);
        vexList.add(v1);
        vexList.add(v2);
        vexList.add(v3);
        vexList.add(v4);
        vexList.add(v5);
        vexList.add(v6);
        vexList.add(v7);
        vexList.add(v8);
        vexList.add(v9);
        vexList.add(v10);
        vexList.add(v11);
        vexList.add(v12);
        vexList.add(v13);
        
        
    }
    
    public boolean topologicalSort() {
        //统计输出顶点数
        int count = 0;
        
        //建栈存储入度为0的顶点
        Stack<Integer> stack = new Stack<>();
        
        //统计入度数(录入也可以,但是示例图的v9的度应为2,示例图中误写为1,导致查了半天bug,自动统计入度数看来也是有必要的)
        for (int i = 0;i < vexList.size(); i++) {
            vexList.get(i).setIn(0);
        }
        for (int i = 0;i < vexList.size(); i++) {
            
            EdgeNode edge = vexList.get(i).getFirstEdge();
            while (edge != null) {
                VertexNode vex = vexList.get(edge.getAdjvex());
                vex.setIn(vex.getIn() + 1);
                
                edge = edge.getNext();
            }
        }
        
        //将入度为0 的顶点入栈
        for (int i = 0;i < vexList.size(); i++) {
            if (vexList.get(i).getIn() == 0) {
                stack.push(i);
            }
        }
        
        while (!stack.isEmpty()) {
            //栈顶 顶点出栈
            int vexIndex = stack.pop();
            System.out.print(vexIndex + "  ");
            
            count++;
            
            //从顶点表结点中取出第一个边表结点
            EdgeNode edge = vexList.get(vexIndex).getFirstEdge();
            
            while (edge != null) {
                int adjvex = edge.getAdjvex();
                
                VertexNode vex = vexList.get(adjvex);
                
                //将此 顶点的入度减一
                vex.setIn(vex.getIn() - 1);
                //此顶点的入度为零则入栈,以便于下次循环输出
                if (vex.getIn() == 0) {
                    stack.push(adjvex);
                }
                
                edge = edge.getNext();
                
            }
        }
        
        if (count != vexList.size())
            return false;
        else
            return true;
    }
    
    public static void main(String[] args) {
        Topological topological = new Topological();
        topological.createGraph();
        boolean success = topological.topologicalSort();
        
        if (success) {
            System.out.println("成功");
        }else {
            System.out.println("失败,有回路");
        }
    }

}

/**
 * 边表结点
 *
 */
class EdgeNode {
    /**
     * 邻接点域,存储该顶点对应的下标
     */
    private int adjvex;
    
    /**
     * 用于存储权值,对于非网图可以不需要
     */
    private int weight;
    
    /**
     * 链域,指向下一个邻接点
     */
    private EdgeNode next;
    
    

    public EdgeNode(int adjvex, int weight, EdgeNode next) {
        super();
        this.adjvex = adjvex;
        this.weight = weight;
        this.next = next;
    }

    public int getAdjvex() {
        return adjvex;
    }

    public void setAdjvex(int adjvex) {
        this.adjvex = adjvex;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public EdgeNode getNext() {
        return next;
    }

    public void setNext(EdgeNode next) {
        this.next = next;
    }
    
    
}

/**
 * 顶点表结点
 *
 */
class VertexNode {
    /**
     * 顶点入度
     */
    private int in;
    
    /**
     * 顶点域,存储顶点信息(下标)
     */
    private int data;
    
    /**
     * 边表头指针
     */
    private EdgeNode firstEdge;
    
    

    public VertexNode(int in, int data, EdgeNode firstEdge) {
        super();
        this.in = in;
        this.data = data;
        this.firstEdge = firstEdge;
    }

    public int getIn() {
        return in;
    }

    public void setIn(int in) {
        this.in = in;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public EdgeNode getFirstEdge() {
        return firstEdge;
    }

    public void setFirstEdge(EdgeNode firstEdge) {
        this.firstEdge = firstEdge;
    }
    
    
}



结果:

java 拓扑图技术_排序算法_03