1 import java.util.*;
2
3 public abstract class AbstractGraph<V> implements Graph<V> {
4 protected List<V> vertices = new ArrayList<>();
5 protected List<List<Edge>> neighbors
6 = new ArrayList<>();
7
8
9 protected AbstractGraph() {
10 }
11
12
13 protected AbstractGraph(V[] vertices, int[][] edges) {
14 for (int i = 0; i < vertices.length; i++)
15 addVertex(vertices[i]);
16
17 createAdjacencyLists(edges, vertices.length);
18 }
19
20
21 protected AbstractGraph(List<V> vertices, List<Edge> edges) {
22 for (int i = 0; i < vertices.size(); i++)
23 addVertex(vertices.get(i));
24
25 createAdjacencyLists(edges, vertices.size());
26 }
27
28
29 protected AbstractGraph(List<Edge> edges, int numberOfVertices) {
30 for (int i = 0; i < numberOfVertices; i++)
31 addVertex((V)(new Integer(i)));
32
33 createAdjacencyLists(edges, numberOfVertices);
34 }
35
36
37 protected AbstractGraph(int[][] edges, int numberOfVertices) {
38 for (int i = 0; i < numberOfVertices; i++)
39 addVertex((V)(new Integer(i)));
40
41 createAdjacencyLists(edges, numberOfVertices);
42 }
43
44
45 private void createAdjacencyLists(
46 int[][] edges, int numberOfVertices) {
47 for (int i = 0; i < edges.length; i++) {
48 addEdge(edges[i][0], edges[i][1]);
49 }
50 }
51
52
53 private void createAdjacencyLists(
54 List<Edge> edges, int numberOfVertices) {
55 for (Edge edge: edges) {
56 addEdge(edge.u, edge.v);
57 }
58 }
59
60 @Override
61 public int getSize() {
62 return vertices.size();
63 }
64
65 @Override
66 public List<V> getVertices() {
67 return vertices;
68 }
69
70 @Override
71 public V getVertex(int index) {
72 return vertices.get(index);
73 }
74
75 @Override
76 public int getIndex(V v) {
77 return vertices.indexOf(v);
78 }
79
80 @Override
81 public List<Integer> getNeighbors(int index) {
82 List<Integer> result = new ArrayList<>();
83 for (Edge e: neighbors.get(index))
84 result.add(e.v);
85
86 return result;
87 }
88
89 @Override
90 public int getDegree(int v) {
91 return neighbors.get(v).size();
92 }
93
94 @Override
95 public void printEdges() {
96 for (int u = 0; u < neighbors.size(); u++) {
97 System.out.print(getVertex(u) + " (" + u + "): ");
98 for (Edge e: neighbors.get(u)) {
99 System.out.print("(" + getVertex(e.u) + ", " +
100 getVertex(e.v) + ") ");
101 }
102 System.out.println();
103 }
104 }
105
106 @Override
107 public void clear() {
108 vertices.clear();
109 neighbors.clear();
110 }
111
112 @Override
113 public boolean addVertex(V vertex) {
114 if (!vertices.contains(vertex)) {
115 vertices.add(vertex);
116 neighbors.add(new ArrayList<Edge>());
117 return true;
118 }
119 else {
120 return false;
121 }
122 }
123
124
125 protected boolean addEdge(Edge e) {
126 if (e.u < 0 || e.u > getSize() - 1)
127 throw new IllegalArgumentException("No such index: " + e.u);
128
129 if (e.v < 0 || e.v > getSize() - 1)
130 throw new IllegalArgumentException("No such index: " + e.v);
131
132 if (!neighbors.get(e.u).contains(e)) {
133 neighbors.get(e.u).add(e);
134 return true;
135 }
136 else {
137 return false;
138 }
139 }
140
141 @Override
142 public boolean addEdge(int u, int v) {
143 return addEdge(new Edge(u, v));
144 }
145
146
147 public static class Edge {
148 public int u;
149 public int v;
150
151
152 public Edge(int u, int v) {
153 this.u = u;
154 this.v = v;
155 }
156
157 public boolean equals(Object o) {
158 return u == ((Edge)o).u && v == ((Edge)o).v;
159 }
160 }
161
162 @Override
163
164 public Tree dfs(int v) {
165 List<Integer> searchOrder = new ArrayList<>();
166 int[] parent = new int[vertices.size()];
167 for (int i = 0; i < parent.length; i++)
168 parent[i] = -1;
169
170
171 boolean[] isVisited = new boolean[vertices.size()];
172
173
174 dfs(v, parent, searchOrder, isVisited);
175
176
177 return new Tree(v, parent, searchOrder);
178 }
179
180
181 private void dfs(int u, int[] parent, List<Integer> searchOrder,
182 boolean[] isVisited) {
183
184 searchOrder.add(u);
185 isVisited[u] = true;
186
187 for (Edge e : neighbors.get(u)) {
188 if (!isVisited[e.v]) {
189 parent[e.v] = u;
190 dfs(e.v, parent, searchOrder, isVisited);
191 }
192 }
193 }
194
195 @Override
196
197 public Tree bfs(int v) {
198 List<Integer> searchOrder = new ArrayList<>();
199 int[] parent = new int[vertices.size()];
200 for (int i = 0; i < parent.length; i++)
201 parent[i] = -1;
202
203 java.util.LinkedList<Integer> queue =
204 new java.util.LinkedList<>();
205 boolean[] isVisited = new boolean[vertices.size()];
206 queue.offer(v);
207 isVisited[v] = true;
208
209 while (!queue.isEmpty()) {
210 int u = queue.poll();
211 searchOrder.add(u);
212 for (Edge e: neighbors.get(u)) {
213 if (!isVisited[e.v]) {
214 queue.offer(e.v);
215 parent[e.v] = u;
216 isVisited[e.v] = true;
217 }
218 }
219 }
220
221 return new Tree(v, parent, searchOrder);
222 }
223
224
225
226 public class Tree {
227 private int root;
228 private int[] parent;
229 private List<Integer> searchOrder;
230
231
232 public Tree(int root, int[] parent, List<Integer> searchOrder) {
233 this.root = root;
234 this.parent = parent;
235 this.searchOrder = searchOrder;
236 }
237
238
239 public int getRoot() {
240 return root;
241 }
242
243
244 public int getParent(int v) {
245 return parent[v];
246 }
247
248
249 public List<Integer> getSearchOrder() {
250 return searchOrder;
251 }
252
253
254 public int getNumberOfVerticesFound() {
255 return searchOrder.size();
256 }
257
258
259 public List<V> getPath(int index) {
260 ArrayList<V> path = new ArrayList<>();
261
262 do {
263 path.add(vertices.get(index));
264 index = parent[index];
265 }
266 while (index != -1);
267
268 return path;
269 }
270
271
272 public void printPath(int index) {
273 List<V> path = getPath(index);
274 System.out.print("A path from " + vertices.get(root) + " to " +
275 vertices.get(index) + ": ");
276 for (int i = path.size() - 1; i >= 0; i--)
277 System.out.print(path.get(i) + " ");
278 }
279
280
281 public void printTree() {
282 System.out.println("Root is: " + vertices.get(root));
283 System.out.print("Edges: ");
284 for (int i = 0; i < parent.length; i++) {
285 if (parent[i] != -1) {
286
287 System.out.print("(" + vertices.get(parent[i]) + ", " +
288 vertices.get(i) + ") ");
289 }
290 }
291 System.out.println();
292 }
293 }
294 }