TopologicalQueue.java


Below is the syntax highlighted version of TopologicalQueue.java from §4.2 Directed Graphs.


/*************************************************************************
 *  Compilation:  javac TopologicalQueue.java
 *  Execution:    java TopologicalQueue V E F
 *  Dependencies: Queue.java
 *
 *  Compute topological ordering of a DAG using queue-based algorithm.
 *  Runs in O(E + V) time.
 *
 *
 *************************************************************************/

public class TopologicalQueue {
    private Queue<Integer> order;     // vertices in topological order
    private int[] indegree;           // indegree[v] = indegree of vertex v
    private int[] rank;               // rank[v] = order where vertex v appers in order
    private int count;                // for computing the ranks

    public TopologicalQueue(Digraph G) {
        indegree = new int[G.V()]; 
        rank = new int[G.V()]; 
        order = new Queue<Integer>();

        // compute indegrees
        for (int v = 0; v < G.V(); v++) {
            for (int w : G.adj(v)) {
                indegree[w]++;
            }
        }

        // initialize queue to contain all vertices with indegree = 0
        Queue<Integer> queue = new Queue<Integer>();
        for (int v = 0; v < G.V(); v++)
            if (indegree[v] == 0) queue.enqueue(v);

        for (int j = 0; !queue.isEmpty(); j++) {
            int v = queue.dequeue();
            order.enqueue(v);
            rank[v] = count++;
            for (int w : G.adj(v)) {
                indegree[w]--;
                if (indegree[w] == 0) queue.enqueue(w);
            }
        }
    }

    // is G a directed acyclic graph?
    public boolean isDAG() {
        for (int v = 0; v < indegree.length; v++)
            if (indegree[v] != 0) return false;
        return true;
    }

    // the vertices in topological order (assuming G is a DAG)
    public Iterable<Integer> order() {
        return order;
    }


    // the rank of vertex v in topological order
    public int rank(int v) {
        return rank[v];
    }

    // certify that digraph is acyclic
    private boolean check(Digraph G) {

        // digraph is acyclic
        if (isDAG()) {
            // check that ranks are a permutation of 0 to V-1
            boolean[] found = new boolean[G.V()];
            for (int i = 0; i < G.V(); i++) {
                found[rank(i)] = true;
            }
            for (int i = 0; i < G.V(); i++) {
                if (!found[i]) {
                    System.err.println("No vertex with rank " + i);
                    return false;
                }
            }

            // check that ranks provide a valid toplogical order
            for (int v = 0; v < G.V(); v++) {
                for (int w : G.adj(v)) {
                    if (rank(v) > rank(w)) {
                        System.err.printf("%d-%d: rank(%d) = %d, rank(%d) = %d\n",
                                          v, w, v, rank(v), w, rank(w));
                        return false;
                    }
                }
            }

            // check that order() is consistent with rank()
            int r = 0;
            for (int v : order()) {
                if (rank(v) != r) {
                    System.err.println("order() and rank() inconsistent");
                    return false;
                }
                r++;
            }
        }


        return true;
    }

    public static void main(String[] args) {

        // create random DAG with V vertices and E edges; then add F random edges
        int V = Integer.parseInt(args[0]);
        int E = Integer.parseInt(args[1]);
        int F = Integer.parseInt(args[2]);
        Digraph G = new Digraph(V);
        int[] vertices = new int[V];
        for (int i = 0; i < V; i++) vertices[i] = i;
        StdRandom.shuffle(vertices);
        for (int i = 0; i < E; i++) {
            int v, w;
            do {
                v = StdRandom.uniform(V);
                w = StdRandom.uniform(V);
            } while (v >= w);
            G.addEdge(vertices[v], vertices[w]);
        }

        // add F extra edges
        for (int i = 0; i < F; i++) {
            int v = (int) (Math.random() * V);
            int w = (int) (Math.random() * V);
            G.addEdge(v, w);
        }

        StdOut.println(G);

        // find a directed cycle
        TopologicalQueue topological = new TopologicalQueue(G);
        if (!topological.isDAG()) {
            StdOut.println("Not a DAG");
        }

        // or give topologial sort
        else {
            StdOut.print("Topological order: ");
            for (int v : topological.order()) {
                StdOut.print(v + " ");
            }
            StdOut.println();
        }
    }

}


Copyright © 2002–2010, Robert Sedgewick and Kevin Wayne.
Last updated: Mon Aug 8 06:45:35 EDT 2011.