|
a |
|
b/network/Graph.java |
|
|
1 |
package network; |
|
|
2 |
|
|
|
3 |
/****************************************************************************** |
|
|
4 |
* Compilation: javac Graph.java |
|
|
5 |
* Execution: java Graph input.txt |
|
|
6 |
* Dependencies: Bag.java Stack.java In.java StdOut.java |
|
|
7 |
* Data files: https://algs4.cs.princeton.edu/41graph/tinyG.txt |
|
|
8 |
* https://algs4.cs.princeton.edu/41graph/mediumG.txt |
|
|
9 |
* https://algs4.cs.princeton.edu/41graph/largeG.txt |
|
|
10 |
* |
|
|
11 |
* A graph, implemented using an array of sets. |
|
|
12 |
* Parallel edges and self-loops allowed. |
|
|
13 |
* |
|
|
14 |
* % java Graph tinyG.txt |
|
|
15 |
* 13 vertices, 13 edges |
|
|
16 |
* 0: 6 2 1 5 |
|
|
17 |
* 1: 0 |
|
|
18 |
* 2: 0 |
|
|
19 |
* 3: 5 4 |
|
|
20 |
* 4: 5 6 3 |
|
|
21 |
* 5: 3 4 0 |
|
|
22 |
* 6: 0 4 |
|
|
23 |
* 7: 8 |
|
|
24 |
* 8: 7 |
|
|
25 |
* 9: 11 10 12 |
|
|
26 |
* 10: 9 |
|
|
27 |
* 11: 9 12 |
|
|
28 |
* 12: 11 9 |
|
|
29 |
* |
|
|
30 |
* % java Graph mediumG.txt |
|
|
31 |
* 250 vertices, 1273 edges |
|
|
32 |
* 0: 225 222 211 209 204 202 191 176 163 160 149 114 97 80 68 59 58 49 44 24 15 |
|
|
33 |
* 1: 220 203 200 194 189 164 150 130 107 72 |
|
|
34 |
* 2: 141 110 108 86 79 51 42 18 14 |
|
|
35 |
* ... |
|
|
36 |
* |
|
|
37 |
******************************************************************************/ |
|
|
38 |
|
|
|
39 |
import java.util.NoSuchElementException; |
|
|
40 |
import java.util.Stack; |
|
|
41 |
|
|
|
42 |
/** |
|
|
43 |
* The {@code Graph} class represents an undirected graph of vertices |
|
|
44 |
* named 0 through <em>V</em> – 1. |
|
|
45 |
* It supports the following two primary operations: add an edge to the graph, |
|
|
46 |
* iterate over all of the vertices adjacent to a vertex. It also provides |
|
|
47 |
* methods for returning the number of vertices <em>V</em> and the number |
|
|
48 |
* of edges <em>E</em>. Parallel edges and self-loops are permitted. |
|
|
49 |
* By convention, a self-loop <em>v</em>-<em>v</em> appears in the |
|
|
50 |
* adjacency list of <em>v</em> twice and contributes two to the degree |
|
|
51 |
* of <em>v</em>. |
|
|
52 |
* <p> |
|
|
53 |
* This implementation uses an adjacency-lists representation, which |
|
|
54 |
* is a vertex-indexed array of {@link Bag} objects. |
|
|
55 |
* All operations take constant time (in the worst case) except |
|
|
56 |
* iterating over the vertices adjacent to a given vertex, which takes |
|
|
57 |
* time proportional to the number of such vertices. |
|
|
58 |
* <p> |
|
|
59 |
* For additional documentation, see <a href="https://algs4.cs.princeton.edu/41graph">Section 4.1</a> |
|
|
60 |
* of <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne. |
|
|
61 |
* |
|
|
62 |
* @author Robert Sedgewick |
|
|
63 |
* @author Kevin Wayne |
|
|
64 |
*/ |
|
|
65 |
public class Graph { |
|
|
66 |
private static final String NEWLINE = System.getProperty("line.separator"); |
|
|
67 |
|
|
|
68 |
private final int V; |
|
|
69 |
private int E; |
|
|
70 |
private Bag<Integer>[] adj; |
|
|
71 |
|
|
|
72 |
/** |
|
|
73 |
* Initializes an empty graph with {@code V} vertices and 0 edges. |
|
|
74 |
* param V the number of vertices |
|
|
75 |
* |
|
|
76 |
* @param V number of vertices |
|
|
77 |
* @throws IllegalArgumentException if {@code V < 0} |
|
|
78 |
*/ |
|
|
79 |
public Graph(int V) { |
|
|
80 |
if (V < 0) throw new IllegalArgumentException("Number of vertices must be nonnegative"); |
|
|
81 |
this.V = V; |
|
|
82 |
this.E = 0; |
|
|
83 |
adj = (Bag<Integer>[]) new Bag[V]; |
|
|
84 |
for (int v = 0; v < V; v++) { |
|
|
85 |
adj[v] = new Bag<Integer>(); |
|
|
86 |
} |
|
|
87 |
} |
|
|
88 |
|
|
|
89 |
/** |
|
|
90 |
* Initializes a graph from the specified input stream. |
|
|
91 |
* The format is the number of vertices <em>V</em>, |
|
|
92 |
* followed by the number of edges <em>E</em>, |
|
|
93 |
* followed by <em>E</em> pairs of vertices, with each entry separated by whitespace. |
|
|
94 |
* |
|
|
95 |
* @param in the input stream |
|
|
96 |
* @throws IllegalArgumentException if the endpoints of any edge are not in prescribed range |
|
|
97 |
* @throws IllegalArgumentException if the number of vertices or edges is negative |
|
|
98 |
* @throws IllegalArgumentException if the input stream is in the wrong format |
|
|
99 |
*/ |
|
|
100 |
public Graph(In in) { |
|
|
101 |
try { |
|
|
102 |
this.V = in.readInt(); |
|
|
103 |
if (V < 0) throw new IllegalArgumentException("number of vertices in a Graph must be nonnegative"); |
|
|
104 |
adj = (Bag<Integer>[]) new Bag[V]; |
|
|
105 |
for (int v = 0; v < V; v++) { |
|
|
106 |
adj[v] = new Bag<Integer>(); |
|
|
107 |
} |
|
|
108 |
int E = in.readInt(); |
|
|
109 |
if (E < 0) throw new IllegalArgumentException("number of edges in a Graph must be nonnegative"); |
|
|
110 |
for (int i = 0; i < E; i++) { |
|
|
111 |
int v = in.readInt(); |
|
|
112 |
int w = in.readInt(); |
|
|
113 |
validateVertex(v); |
|
|
114 |
validateVertex(w); |
|
|
115 |
addEdge(v, w); |
|
|
116 |
} |
|
|
117 |
} |
|
|
118 |
catch (NoSuchElementException e) { |
|
|
119 |
throw new IllegalArgumentException("invalid input format in Graph constructor", e); |
|
|
120 |
} |
|
|
121 |
} |
|
|
122 |
|
|
|
123 |
|
|
|
124 |
/** |
|
|
125 |
* Initializes a new graph that is a deep copy of {@code G}. |
|
|
126 |
* |
|
|
127 |
* @param G the graph to copy |
|
|
128 |
*/ |
|
|
129 |
public Graph(Graph G) { |
|
|
130 |
this(G.V()); |
|
|
131 |
this.E = G.E(); |
|
|
132 |
for (int v = 0; v < G.V(); v++) { |
|
|
133 |
// reverse so that adjacency list is in same order as original |
|
|
134 |
Stack<Integer> reverse = new Stack<Integer>(); |
|
|
135 |
for (int w : G.adj[v]) { |
|
|
136 |
reverse.push(w); |
|
|
137 |
} |
|
|
138 |
for (int w : reverse) { |
|
|
139 |
adj[v].add(w); |
|
|
140 |
} |
|
|
141 |
} |
|
|
142 |
} |
|
|
143 |
|
|
|
144 |
/** |
|
|
145 |
* Returns the number of vertices in this graph. |
|
|
146 |
* |
|
|
147 |
* @return the number of vertices in this graph |
|
|
148 |
*/ |
|
|
149 |
public int V() { |
|
|
150 |
return V; |
|
|
151 |
} |
|
|
152 |
|
|
|
153 |
/** |
|
|
154 |
* Returns the number of edges in this graph. |
|
|
155 |
* |
|
|
156 |
* @return the number of edges in this graph |
|
|
157 |
*/ |
|
|
158 |
public int E() { |
|
|
159 |
return E; |
|
|
160 |
} |
|
|
161 |
|
|
|
162 |
// throw an IllegalArgumentException unless {@code 0 <= v < V} |
|
|
163 |
private void validateVertex(int v) { |
|
|
164 |
if (v < 0 || v >= V) |
|
|
165 |
throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1)); |
|
|
166 |
} |
|
|
167 |
|
|
|
168 |
/** |
|
|
169 |
* Adds the undirected edge v-w to this graph. |
|
|
170 |
* |
|
|
171 |
* @param v one vertex in the edge |
|
|
172 |
* @param w the other vertex in the edge |
|
|
173 |
* @throws IllegalArgumentException unless both {@code 0 <= v < V} and {@code 0 <= w < V} |
|
|
174 |
*/ |
|
|
175 |
public void addEdge(int v, int w) { |
|
|
176 |
validateVertex(v); |
|
|
177 |
validateVertex(w); |
|
|
178 |
E++; |
|
|
179 |
adj[v].add(w); |
|
|
180 |
adj[w].add(v); |
|
|
181 |
} |
|
|
182 |
|
|
|
183 |
|
|
|
184 |
/** |
|
|
185 |
* Returns the vertices adjacent to vertex {@code v}. |
|
|
186 |
* |
|
|
187 |
* @param v the vertex |
|
|
188 |
* @return the vertices adjacent to vertex {@code v}, as an iterable |
|
|
189 |
* @throws IllegalArgumentException unless {@code 0 <= v < V} |
|
|
190 |
*/ |
|
|
191 |
public Iterable<Integer> adj(int v) { |
|
|
192 |
validateVertex(v); |
|
|
193 |
return adj[v]; |
|
|
194 |
} |
|
|
195 |
|
|
|
196 |
/** |
|
|
197 |
* Returns the degree of vertex {@code v}. |
|
|
198 |
* |
|
|
199 |
* @param v the vertex |
|
|
200 |
* @return the degree of vertex {@code v} |
|
|
201 |
* @throws IllegalArgumentException unless {@code 0 <= v < V} |
|
|
202 |
*/ |
|
|
203 |
public int degree(int v) { |
|
|
204 |
validateVertex(v); |
|
|
205 |
return adj[v].size(); |
|
|
206 |
} |
|
|
207 |
|
|
|
208 |
|
|
|
209 |
/** |
|
|
210 |
* Returns a string representation of this graph. |
|
|
211 |
* |
|
|
212 |
* @return the number of vertices <em>V</em>, followed by the number of edges <em>E</em>, |
|
|
213 |
* followed by the <em>V</em> adjacency lists |
|
|
214 |
*/ |
|
|
215 |
public String toString() { |
|
|
216 |
StringBuilder s = new StringBuilder(); |
|
|
217 |
s.append(V + " vertices, " + E + " edges " + NEWLINE); |
|
|
218 |
for (int v = 0; v < V; v++) { |
|
|
219 |
s.append(v + ": "); |
|
|
220 |
for (int w : adj[v]) { |
|
|
221 |
s.append(w + " "); |
|
|
222 |
} |
|
|
223 |
s.append(NEWLINE); |
|
|
224 |
} |
|
|
225 |
return s.toString(); |
|
|
226 |
} |
|
|
227 |
|
|
|
228 |
|
|
|
229 |
/** |
|
|
230 |
* Unit tests the {@code Graph} data type. |
|
|
231 |
* |
|
|
232 |
* @param args the command-line arguments |
|
|
233 |
*/ |
|
|
234 |
public static void main(String[] args) { |
|
|
235 |
In in = new In(args[0]); |
|
|
236 |
Graph G = new Graph(in); |
|
|
237 |
StdOut.println(G); |
|
|
238 |
} |
|
|
239 |
|
|
|
240 |
} |
|
|
241 |
|