拓扑排序

来源:互联网 发布:淘宝首页装修全屏 编辑:程序博客网 时间:2024/05/17 00:52

关于拓扑排序

  • 待排序的元素是什么? —— 有向图的结点

  • 按怎样的顺序? —— 如果存在边 v→w,则v要排在w的前面

算法

  • list ← []

  • 初始化队列,将入度为0的结点加入队列

    • 当队列非空:
      • v ← 出队
      • list.add(v)
      • w ← 遍历与v相邻的顶点
        • 将w的度数减1
        • 如果w的度数为0,则将w加入队列
  • 如果 list.size() < 顶点总数,则抛出有环异常

实现

package com.gmail.dailyefforts.ds.graph;import java.io.FileInputStream;import java.util.ArrayList;import java.util.LinkedList;import java.util.List;import java.util.Queue;import java.util.Scanner;public class TopoSort {    public static List<Integer> topoSort(DirectedGraph g) {        List<Integer> list = new ArrayList<>();        Queue<Vertex> q = new LinkedList<>();        for (Vertex v : g.vertices()) {            if (v.inDegree == 0) {                q.add(v);            }        }        while (!q.isEmpty()) {            Vertex v = q.poll();            list.add(v.id);            for (Vertex w : v.adj()) {                if (--w.inDegree == 0) {                    q.add(w);                }            }        }        if (list.size() < g.V()) {            throw new RuntimeException("There is cycle.");        }        return list;    }    public static void main(String[] args) throws Exception {        Scanner sc = new Scanner(new FileInputStream("./input.txt"));        final int V = sc.nextInt();        final int E = sc.nextInt();        DirectedGraph g = new DirectedGraph(V);        for (int e = 0; e < E; e++) {            int v = sc.nextInt();            int w = sc.nextInt();            g.addEdge(v, w);        }        System.out.println(TopoSort.topoSort(g));        sc.close();    }}

相关有向图的实现:

package com.gmail.dailyefforts.ds.graph;import java.io.FileInputStream;import java.util.ArrayList;import java.util.List;import java.util.Scanner;public class DirectedGraph {    private final int V;    private int E;    private List<Vertex> vertices;    public DirectedGraph(int V) {        this.V = V;        vertices = new ArrayList<>();        for (int v = 0; v < V; v++) {            vertices.add(new Vertex(v));        }    }    public int V() {        return V;    }    public int E() {        return E;    }    public void addEdge(int from, int to) {        Vertex v = vertices.get(from);        Vertex w = vertices.get(to);        v.addAdj(w);        v.outDegree++;        w.inDegree++;        E++;    }    public int inDegree(int v) {        Vertex vertex = vertices.get(v);        return vertex.inDegree;    }    public int outDegree(int v) {        Vertex vertex = vertices.get(v);        return vertex.outDegree;    }    public Iterable<Vertex> vertices() {        return vertices;    }    @Override    public String toString() {        StringBuilder builder = new StringBuilder();        builder.append(String.format("%d vertices, %d edges\n", V, E));        for (int v = 0; v < V; v++) {            builder.append(v + ": " + vertices.get(v).adj);            builder.append('\n');        }        return builder.toString();    }    public static void main(String[] args) throws Exception {        Scanner sc = new Scanner(new FileInputStream("./input.txt"));        final int V = sc.nextInt();        final int E = sc.nextInt();        DirectedGraph g = new DirectedGraph(V);        for (int e = 0; e < E; e++) {            int v = sc.nextInt();            int w = sc.nextInt();            g.addEdge(v, w);        }        System.out.println(g);        sc.close();    }}

实例

有向图

拓扑排序:0, 1, 2, 4, 3

应用

拓扑排序可用于任务调度,例如,C语言算法的先修课程,算法操作系统的先修课程。我们就应该在时序上做如此安排:C语言算法操作系统

0 0
原创粉丝点击