This repository has been archived by the owner on Mar 30, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GraphUtility.java
182 lines (155 loc) · 6.56 KB
/
GraphUtility.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package assign07;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
/**
* Contains several methods for solving problems on generic, directed,
* unweighted, sparse graphs.
*
* @author Erin Parker, Paul Nuffer & Nils Streedain
* @version March 10, 2021
*/
public class GraphUtility {
/**
* @param <Type> the ID type for the graph
* @param sources - the list of source IDs
* @param destinations - the list of destinations IDs
* @return a Graph object containing Vertices with Edges properly representing
* the graph of IDs
*/
private static <Type> Graph<Type> createGraphFromLists(List<Type> sources, List<Type> destinations) {
Graph<Type> graph = new Graph<>();
Iterator<Type> sourcesIterator = sources.iterator();
Iterator<Type> destinationsIterator = destinations.iterator();
while (sourcesIterator.hasNext() && destinationsIterator.hasNext())
graph.addEdge(sourcesIterator.next(), destinationsIterator.next());
return graph;
}
/**
* (Driver Method) This method must use the depth-first search algorithm
* presented in lecture to determine whether there is a path from the vertex
* with srcData to the vertex with dstData in the graph. Throws an
* IllegalArgumentException if there does not exist a vertex in the graph with
* srcData, and likewise for dstData.
*
* @param <Type> The generic type for the ID of each vertex in the graph
* @param sources - a list of sources
* @param destinations - a list of destinations
* @param srcData - the beginning vertex to start at
* @param dstData - the vertex to reach
* @return true if the two vertexes are connected, false otherwise
* @throws IllegalArgumentException if there does not exist a vertex in the
* graph with srcData or dstData
*/
public static <Type> boolean areConnected(List<Type> sources, List<Type> destinations, Type srcData, Type dstData)
throws IllegalArgumentException {
Graph<Type> graphToTraverse = createGraphFromLists(sources, destinations);
return graphToTraverse.areConnected(srcData, dstData);
}
/**
* This method must use the breadth-first search algorithm presented in lecture
* to find a shortest path from the vertex with srcData to the vertex with
* dstData in the graph.
*
* @param <Type> The generic type for the ID of each vertex in the graph
* @param sources - a list of sources
* @param destinations - a list of destinations
* @param srcData - the beginning vertex to start at
* @param dstData - the vertex to find the shortest path to
* @return an ordered list containing the shortest path from srcData to dstData
* @throws IllegalArgumentException if there does not exist a vertex in the
* graph with srcData, and likewise for
* dstData. Also, throws an
* IllegalArgumentException if there does not
* exist a path between the two vertices.
*/
public static <Type> List<Type> shortestPath(List<Type> sources, List<Type> destinations, Type srcData,
Type dstData) throws IllegalArgumentException {
Graph<Type> graphToTraverse = createGraphFromLists(sources, destinations);
return graphToTraverse.shortestPath(srcData, dstData);
}
/**This method topographically sorts the graph passed in via the sources and destinations lists.
* @param <Type> The generic type for the ID of each vertex in the graph
* @param sources - a list of sources
* @param destinations - a list of destinations
* @return a new list with all IDs sorted in topographical sort order
* @throws IllegalArgumentException if the graph contains a cycle
*/
public static <Type> List<Type> sort(List<Type> sources, List<Type> destinations) throws IllegalArgumentException {
Graph<Type> graphToTraverse = createGraphFromLists(sources, destinations);
return graphToTraverse.sort();
}
/**
* Builds "sources" and "destinations" lists according to the edges specified in
* the given DOT file (e.g., "a -> b"). Assumes that the vertex data type is
* String.
*
* Accepts many valid "digraph" DOT files (see examples posted on Canvas).
* --accepts \\-style comments --accepts one edge per line or edges terminated
* with ; --does not accept attributes in [] (e.g., [label = "a label"])
*
* @param filename - name of the DOT file
* @param sources - empty ArrayList, when method returns it is a valid
* "sources" list that can be passed to the public methods
* in this class
* @param destinations - empty ArrayList, when method returns it is a valid
* "destinations" list that can be passed to the public
* methods in this class
*/
public static void buildListsFromDot(String filename, ArrayList<String> sources, ArrayList<String> destinations) {
Scanner scan = null;
try {
scan = new Scanner(new File(filename));
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
System.exit(0);
}
scan.useDelimiter(";|\n");
// Determine if graph is directed (i.e., look for "digraph id {").
String line = "", edgeOp = "";
while (scan.hasNext()) {
line = scan.next();
// Skip //-style comments.
line = line.replaceFirst("//.*", "");
if (line.indexOf("digraph") >= 0) {
edgeOp = "->";
line = line.replaceFirst(".*\\{", "");
break;
}
}
if (edgeOp.equals("")) {
System.out.println("DOT graph must be directed (i.e., digraph).");
scan.close();
System.exit(0);
}
// Look for edge operator -> and determine the source and destination
// vertices for each edge.
while (scan.hasNext()) {
String[] substring = line.split(edgeOp);
for (int i = 0; i < substring.length - 1; i += 2) {
// remove " and trim whitespace from node string on the left
String vertex1 = substring[0].replace("\"", "").trim();
// if string is empty, try again
if (vertex1.equals(""))
continue;
// do the same for the node string on the right
String vertex2 = substring[1].replace("\"", "").trim();
if (vertex2.equals(""))
continue;
// indicate edge between vertex1 and vertex2
sources.add(vertex1);
destinations.add(vertex2);
}
// do until the "}" has been read
if (substring[substring.length - 1].indexOf("}") >= 0)
break;
line = scan.next();
// Skip //-style comments.
line = line.replaceFirst("//.*", "");
}
scan.close();
}
}