130 lines
3.6 KiB
Java
130 lines
3.6 KiB
Java
|
|
||
|
|
||
|
import edu.princeton.cs.introcs.In;
|
||
|
import edu.princeton.cs.introcs.StdOut;
|
||
|
|
||
|
/*************************************************************************
|
||
|
* Compilation: javac DepthFirstPaths.java
|
||
|
* Execution: java DepthFirstPaths G s
|
||
|
* Dependencies: Graph.java Stack.java StdOut.java
|
||
|
* Data files: http://algs4.cs.princeton.edu/41undirected/tinyCG.txt
|
||
|
*
|
||
|
* Run depth first search on an undirected graph.
|
||
|
* Runs in O(E + V) time.
|
||
|
*
|
||
|
* % java Graph tinyCG.txt
|
||
|
* 6 8
|
||
|
* 0: 2 1 5
|
||
|
* 1: 0 2
|
||
|
* 2: 0 1 3 4
|
||
|
* 3: 5 4 2
|
||
|
* 4: 3 2
|
||
|
* 5: 3 0
|
||
|
*
|
||
|
* % java DepthFirstPaths tinyCG.txt 0
|
||
|
* 0 to 0: 0
|
||
|
* 0 to 1: 0-2-1
|
||
|
* 0 to 2: 0-2
|
||
|
* 0 to 3: 0-2-3
|
||
|
* 0 to 4: 0-2-3-4
|
||
|
* 0 to 5: 0-2-3-5
|
||
|
*
|
||
|
*************************************************************************/
|
||
|
|
||
|
/**
|
||
|
* The DepthFirstPaths class represents a data type for finding
|
||
|
* paths from a source vertex s to every other vertex
|
||
|
* in an undirected graph.
|
||
|
*
|
||
|
* This implementation uses depth-first search.
|
||
|
* The constructor takes time proportional to V + E ,
|
||
|
* where V is the number of vertices and E is the number of edges.
|
||
|
* It uses extra space (not including the graph) proportional to V .
|
||
|
*
|
||
|
* For additional documentation, see <a href="/algs4/41graph">Section 4.1</a> of
|
||
|
* Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
|
||
|
*
|
||
|
* @author Robert Sedgewick
|
||
|
* @author Kevin Wayne
|
||
|
*/
|
||
|
public class DepthFirstPaths {
|
||
|
private boolean[] marked; // marked[v] = is there an s-v path?
|
||
|
private int[] edgeTo; // edgeTo[v] = last edge on s-v path
|
||
|
private final int s; // source vertex
|
||
|
|
||
|
/**
|
||
|
* Computes a path between s and every other vertex in graph G .
|
||
|
* @param G the graph
|
||
|
* @param s the source vertex
|
||
|
*/
|
||
|
public DepthFirstPaths(Graph G, int s) {
|
||
|
this.s = s;
|
||
|
edgeTo = new int[G.V()];
|
||
|
marked = new boolean[G.V()];
|
||
|
dfs(G, s);
|
||
|
}
|
||
|
|
||
|
// depth first search from v
|
||
|
private void dfs(Graph G, int v) {
|
||
|
marked[v] = true;
|
||
|
for (int w : G.adj(v)) {
|
||
|
if (!marked[w]) {
|
||
|
edgeTo[w] = v;
|
||
|
dfs(G, w);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Is there a path between the source vertex s and vertex v ?
|
||
|
* @param v the vertex
|
||
|
* @return true if there is a path, false otherwise
|
||
|
*/
|
||
|
public boolean hasPathTo(int v) {
|
||
|
return marked[v];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a path between the source vertex s and vertex v , or
|
||
|
* null if no such path.
|
||
|
* @param v the vertex
|
||
|
* @return the sequence of vertices on a path between the source vertex
|
||
|
* s and vertex v , as an Iterable
|
||
|
*/
|
||
|
public Iterable<Integer> pathTo(int v) {
|
||
|
if (!hasPathTo(v)) return null;
|
||
|
Stack<Integer> path = new Stack<Integer>();
|
||
|
for (int x = v; x != s; x = edgeTo[x])
|
||
|
path.push(x);
|
||
|
path.push(s);
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Unit tests the DepthFirstPaths data type.
|
||
|
*/
|
||
|
public static void main(String[] args) {
|
||
|
In in = new In(args[0]);
|
||
|
Graph G = new Graph(in);
|
||
|
int s = Integer.parseInt(args[1]);
|
||
|
DepthFirstPaths dfs = new DepthFirstPaths(G, s);
|
||
|
|
||
|
for (int v = 0; v < G.V(); v++) {
|
||
|
if (dfs.hasPathTo(v)) {
|
||
|
StdOut.printf("%d to %d: ", s, v);
|
||
|
for (int x : dfs.pathTo(v)) {
|
||
|
if (x == s) StdOut.print(x);
|
||
|
else StdOut.print("-" + x);
|
||
|
}
|
||
|
StdOut.println();
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
StdOut.printf("%d to %d: not connected\n", s, v);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|