A self-loop is an edge that connects a vertex to itself.
Two edges are parallel if they connect the same ordered pair of vertices.
The outdegree of a vertex is the number of edges pointing from it.
The indegree of a vertex is the number of edges pointing to it.
A subgraph is a subset of a digraph's edges (and associated vertices) that constitutes a digraph.
A directed path in a digraph is a sequence of vertices in which there is a (directed) edge pointing from each vertex in the sequence to its successor in the sequence, with no repeated edges.
A directed path is simple if it has no repeated vertices.
A directed cycle is a directed path (with at least one edge) whose first and last vertices are the same.
A directed cycle is simple if it has no repeated vertices (other than the requisite repetition of the first and last vertices).
The length of a path or a cycle is its number of edges.
We say that a vertex w is reachable from a vertex v if there exists a directed path from v to w.
We say that two vertices v and w are strongly connected if they are mutually reachable: there is a directed path from v to w and a directed path from w to v.
A digraph is strongly connected if there is a directed path from every vertex to every other vertex.
A digraph that is not strongly connected consists of a set of strongly connected components, which are maximal strongly connected subgraphs.
A directed acyclic graph (or DAG) is a digraph with no directed cycles.
DiGraph: Set of vertices connect pairwise by directed edges
Iterate over vertices adjacent to v - outdegree(v)
Depth First Search
Java implementation is same as undirected graph
Breadth First Search
Java implementation is same as undirected graph
Depth First Order
Depth-first search search visits each vertex exactly once. Three vertex orderings are of interest in typical applications:
Preorder: Put the vertex on a queue before the recursive calls.
Postorder: Put the vertex on a queue after the recursive calls.
Reverse postorder: Put the vertex on a stack after the recursive calls.
Java Implementation
/****************************************************************************** * Compilation: javac DepthFirstOrder.java * Execution: java DepthFirstOrder digraph.txt * Dependencies: Digraph.java Queue.java Stack.java StdOut.java * EdgeWeightedDigraph.java DirectedEdge.java * Data files: https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt * https://algs4.cs.princeton.edu/42digraph/tinyDG.txt * * Compute preorder and postorder for a digraph or edge-weighted digraph. * Runs in O(E + V) time. * * % java DepthFirstOrder tinyDAG.txt * v pre post * -------------- * 0 0 8 * 1 3 2 * 2 9 10 * 3 10 9 * 4 2 0 * 5 1 1 * 6 4 7 * 7 11 11 * 8 12 12 * 9 5 6 * 10 8 5 * 11 6 4 * 12 7 3 * Preorder: 0 5 4 1 6 9 11 12 10 2 3 7 8 * Postorder: 4 5 1 12 11 10 9 6 0 3 2 7 8 * Reverse postorder: 8 7 2 3 0 6 9 10 11 12 1 5 4 * ******************************************************************************//** * The {@code DepthFirstOrder} class represents a data type for * determining depth-first search ordering of the vertices in a digraph * or edge-weighted digraph, including preorder, postorder, and reverse postorder. * <p> * This implementation uses depth-first search. * Each constructor takes Θ(<em>V</em> + <em>E</em>) time, * where <em>V</em> is the number of vertices and <em>E</em> is the * number of edges. * Each instance method takes Θ(1) time. * It uses Θ(<em>V</em>) extra space (not including the digraph). * <p> * For additional documentation, * see <a href="https://algs4.cs.princeton.edu/42digraph">Section 4.2</a> of * <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne. * * @author Robert Sedgewick * @author Kevin Wayne */publicclassDepthFirstOrder {privateboolean[] marked; // marked[v] = has v been marked in dfs?privateint[] pre; // pre[v] = preorder number of vprivateint[] post; // post[v] = postorder number of vprivateQueue<Integer> preorder; // vertices in preorderprivateQueue<Integer> postorder; // vertices in postorderprivateint preCounter; // counter or preorder numberingprivateint postCounter; // counter for postorder numbering /** * Determines a depth-first order for the digraph {@code G}. * @param G the digraph */publicDepthFirstOrder(Digraph G) { pre =newint[G.V()]; post =newint[G.V()]; postorder =newQueue<Integer>(); preorder =newQueue<Integer>(); marked =newboolean[G.V()];for (int v =0; v <G.V(); v++)if (!marked[v]) dfs(G, v);assertcheck(); } /** * Determines a depth-first order for the edge-weighted digraph {@code G}. * @param G the edge-weighted digraph */publicDepthFirstOrder(EdgeWeightedDigraph G) { pre =newint[G.V()]; post =newint[G.V()]; postorder =newQueue<Integer>(); preorder =newQueue<Integer>(); marked =newboolean[G.V()];for (int v =0; v <G.V(); v++)if (!marked[v]) dfs(G, v); }// run DFS in digraph G from vertex v and compute preorder/postorderprivatevoiddfs(Digraph G,int v) { marked[v] =true; pre[v] = preCounter++;preorder.enqueue(v);for (int w :G.adj(v)) {if (!marked[w]) {dfs(G, w); } }postorder.enqueue(v); post[v] = postCounter++; }// run DFS in edge-weighted digraph G from vertex v and compute preorder/postorderprivatevoiddfs(EdgeWeightedDigraph G,int v) { marked[v] =true; pre[v] = preCounter++;preorder.enqueue(v);for (DirectedEdge e :G.adj(v)) {int w =e.to();if (!marked[w]) {dfs(G, w); } }postorder.enqueue(v); post[v] = postCounter++; } /** * Returns the preorder number of vertex {@code v}. * @param v the vertex * @return the preorder number of vertex {@code v} * @throwsIllegalArgumentException unless {@code 0 <= v < V} */publicintpre(int v) {validateVertex(v);return pre[v]; } /** * Returns the postorder number of vertex {@code v}. * @param v the vertex * @return the postorder number of vertex {@code v} * @throwsIllegalArgumentException unless {@code 0 <= v < V} */publicintpost(int v) {validateVertex(v);return post[v]; } /** * Returns the vertices in postorder. * @return the vertices in postorder, as an iterable of vertices */publicIterable<Integer> post() {return postorder; } /** * Returns the vertices in preorder. * @return the vertices in preorder, as an iterable of vertices */publicIterable<Integer> pre() {return preorder; } /** * Returns the vertices in reverse postorder. * @return the vertices in reverse postorder, as an iterable of vertices */publicIterable<Integer> reversePost() {Stack<Integer> reverse =newStack<Integer>();for (int v : postorder)reverse.push(v);return reverse; }// check that pre() and post() are consistent with pre(v) and post(v)privatebooleancheck() {// check that post(v) is consistent with post()int r =0;for (int v :post()) {if (post(v)!= r) {StdOut.println("post(v) and post() inconsistent");returnfalse; } r++; }// check that pre(v) is consistent with pre() r =0;for (int v :pre()) {if (pre(v)!= r) {StdOut.println("pre(v) and pre() inconsistent");returnfalse; } r++; }returntrue; }// throw an IllegalArgumentException unless {@code 0 <= v < V}privatevoidvalidateVertex(int v) {int V =marked.length;if (v <0|| v >= V)thrownewIllegalArgumentException("vertex "+ v +" is not between 0 and "+ (V-1)); } /** * Unit tests the {@code DepthFirstOrder} data type. * * @param args the command-line arguments */publicstaticvoidmain(String[] args) {In in =newIn(args[0]);Digraph G =newDigraph(in);DepthFirstOrder dfs =newDepthFirstOrder(G);StdOut.println(" v pre post");StdOut.println("--------------");for (int v =0; v <G.V(); v++) {StdOut.printf("%4d %4d %4d\n", v,dfs.pre(v),dfs.post(v)); }StdOut.print("Preorder: ");for (int v :dfs.pre()) {StdOut.print(v +" "); }StdOut.println();StdOut.print("Postorder: ");for (int v :dfs.post()) {StdOut.print(v +" "); }StdOut.println();StdOut.print("Reverse postorder: ");for (int v :dfs.reversePost()) {StdOut.print(v +" "); }StdOut.println(); }}