
Due: Mon, Apr 20, by 11:59pm
|
| Due: Thu, Apr 23, by 11:59pm |
Graph is a collection of Vertices connected by Edges. It is a generalization of the Tree data structure from the previous assignments.
The focus is on the following algorithms and data structures:
assertEquals. Instead each @Test method will look like a mini-main method and you will inspect the console to see if the output is correct.
[ To test individual components you can comment //@Test ]
Here is an example:
@Test
public void test_bfs()
{
Graph graph = new Graph("undirected.txt");
String[] labelsList = { "a", ... };
for ( ... ) {
System.out.println("Source: ?");
GraphAlgos.bfs(graph, ?);
}
}
|
@Test
public void test_dijkstra()
{
Graph graph = new Graph("directed.txt");
String[] labelsList = { "a", ... };
for ( ... ) {
System.out.println("Source: ?");
GraphAlgos.dijkstra(graph, ?);
}
}
|
@Test
public void test_dfs()
{
Graph graph = new Graph("directed.txt");
String[] labelsList = { "a", ... };
for ( ... ) {
System.out.println("Source: ?");
GraphAlgos.dfs(graph, ?);
}
}
|
default (i.e. non-private) as in the previous Node classes:
Each vertex will have the following data members:
Vertex(String theLabel) - creates a blank vertex with the given text and integer labelstoString() - returns a string representation of this vertex in the following format:
MyLabel:MyDist:MyParentLabel i.e. Hanover:15:NewOxford
Edge is described by its source and target vertices, and by its weight.
The interface for the Edge class is:
Egde(Vertex theSource, Vertex theTarget, double theWeight)Vertex getSource()Vertex getTarget()double getWeight()Graph should use the adjacency list representation based on a HashMap with (key,value)=(?,?).
The graph data members:
edge map - associates a vertex label with a list of edgesvertex map - associates a vertex label with a vertexedge map)Graph class:
Graph(String filename)
Reads a graph from the file with the given
filename (see Scanner API).
Make sure to use the appropriate constructor to open the file. If Eclipse does not suggest adding try/catch, you are using the wrong Scanner constructor.
Methods .next() and .nextDouble() will read a single string and a single double, respectively. Method hasNext() will determine when to stop.
The files are formatted as follows:
source target weight src/, bin/):
|
||
Graph()
This constructor is not required, but you might use it initially if you are not sure whether you can read from a file.
This is just a sequence of
addEgde calls for each line in the file you want to test.
public Graph()
{
// any intialization
// for BFS load "undirected.txt"
// addEdge("a", "b", 2);
// addEdge("a", "f", 7);
// addEdge("a", "g", 3);
// addEdge("a", "b", 2);
...
USE ONLY ONE OR THE OTHER
// for Dijkstra/DFS load "directed.txt"
// addEdge("a", "b", 4);
// addEdge("a", "f", 2);
// addEdge("b", "c", 3);
....
}
|
||
void addEdge(String sourceLabel, String targetLabel, double weight)
Adds an edge with the given weight from the vertex with the given source label to the vertex with the given target label.
Make sure duplicate vertices are not created. In other words, if called multiple times with
sourceLabel or targetLabel "Gettysburg" it should always use the same Vertex object for "Gettysburg".
|
||
Vertex getVertex(String label)
Returns a
Vertex object for the given label.
It should ensure that vertices are constructed/setup properly.
|
||
List<Edge> getAdjacent(Vertex source)
Returns an unmodifiable list of the edges that have the given vertex as their
source.
[ Initially ignore the unmodifiable part. Later see the relevant method in the Collections API. ]
|
||
Collection<Vertex> getVertices()
Returns an unmodifiable collection of the vertices in the
graph.
[ Initially ignore the unmodifiable part. Later see the relevant method in the Collections API. ]
|
GraphAlgos and implement the Breadth-First Search and Depth-First Search graph traversal algorithms by adding the following methods:
static void __method__(Graph graph)
A useful helper method...
|
static void bfs(Graph graph, String sourceLabel)
Performs Breadth-First Search (pseudocode) on the given
graph starting at the given source vertex. This is essentially Level Order with vertex marking; see Figure 4.3 in [ALG].
The vertices are displayed on one line separated by a space in the order they are finished in the format:
a:0:* b:1:a f:1:a g:1:a c:2:b e:2:f i:2:f h:2:g d:3:cBFS results on undirected.txt for each vertex as source
|
static void dfs(Graph graph, String sourceLabel)
Performs Depth-First Search on the given
graph starting at the given source vertex. See Figures 3.5 and 3.3 in [ALG].
This method simply calls the next method after carrying out any preliminary steps (if necessary).
The vertices are displayed on one line separated by a space in the order they are finished in the format:
a:0:* b:1:a c:2:b d:3:c e:4:d f:1:aDFS results on directed.txt for each vertex as source |
static void dfs(Graph graph, Vertex curr)
Uses recursion to perform Depth First Search on the given
graph starting at the given vertex curr. See Figures 3.5 and 3.3 in [ALG].
Depth-First Search is a generalization of the Preorder Traversal of BSTree: in each case first "process" the circle and then "process" all arrows for that circle.
The major difference between "peorder traversal" for BSTree and Graph is that in the case of Graph the vertices/nodes need to be marked and the other bookkeeping fields need to be updated (marking is needed to ignore traversing a vertex again after it has been traversed/marked by someone else).
For simplicity, "processing vertex" for Graph will simply print the string representation of the vertex.
|
GraphAlgos.
static void dijkstra(Graph graph, String sourceLabel)
Computes the shortest paths from the given
source vertex to all the other vertices in the given graph using Dijkstra's algorithm (pseudocode).
You will need to create VertexComparator.
As soon as a vertex is finished:
PQ.
|
static void printPathLoop(Vertex startVertex, Vertex destVertex)
Uses a loop to print the path (in reverse) from the given destination vertex to the given starting vertex.
[ During the execution of Dijkstra's Algorithm the source will always be given as the starting vertex when this method is called. ]
The path is printed in the following format:
F <--5-- D <--2-- G <--6-- C <--4-- A (total length 17) A is the original source and F is the destination, and the path is printed in reverse (this makes the problem simpler).
Note: The individual numbers are edge lengths, not cumulative distances.
This method will be tested indirectly by testing Dijkstra's algorithm.
|
static void printPathRec(Vertex startVertex, Vertex destVertex)
Same as method
printPath but uses recursion (does not include the total length). Unlike the previous method, this one shows the path from the startVertex to the given destVertex, i.e. not in reverse.
A --4--> C --6--> G --2--> D --5--> F A is the source and F is the destination, and the path is printed correctly. This makes the problem harder (but total distance is not printed).
Note: The individual numbers are edge lengths, not cumulative distances.
This method will be tested indirectly by testing Dijkstra's algorithm.
|
main method to class GraphAlgos:
main run the various algorithms with hardcoded input files and source verticesmain to use its command-line arguments from the String[] parameter: