Reputation: 129
I am trying to implement a method isReachable(E fromKey, E toKey)
to determine if any path exists between the two specified vertices in the graph. I have a generic class Graph<E>
that uses two inner data structures, Vertex
and Edge
, to represent the vertices and edges of the graph. Here is the code for that:
public class Graph<E extends Comparable<E>> implements GraphAPI<E>
{
/*
* number of vertices (size of this graph)
*/
private long order;
/**
* pointer to the list of vertices
*/
private Vertex first;
/**
* A vertex of a graph stores a data item and references
* to its edge list and the succeeding vertex. The data
* object extends the comparable interface.
*/
private class Vertex
{
/**
* pointer to the next vertex
*/
public Vertex pNextVertex;
/**
* the data item
*/
public E data;
/**
* indegree
*/
public long inDeg;
/**
* outdegree
*/
public long outDeg;
/**
* pointer to the edge list
*/
public Edge pEdge;
/**
* Field for tracking vertex accesses
*/
public long processed;
}
/**
* An edge of a graph contains a reference to the destination
* vertex, a reference to the succeeding edge in the edge list and
* the weight of the directed edge.
*/
private class Edge
{
/**
* pointer to the destination vertex
*/
public Vertex destination;
/**
* weight on this edge
*/
public Double weight;
/**
* pointer to the next edge
*/
public Edge pNextEdge;
}
/**
* Constructs an empty weighted directed graph
*/
public Graph()
{
first = null;
order = 0;
}
}
This is my thought process:
(1) Walk through the list of vertices until reaching the Vertex containing the specified fromKey
; (2) add each adjacent Vertex to the fromKey
to a queue; (3) while the queue is not empty, retrieve and remove the Vertex at the head of the queue and compare it's key to the toKey
; and (4) if it's a match return true, otherwise keep searching through the edge list of each adjacent Vertex.
Here is my code for the method so far:
/**
* Determines whether there is an outdirected path between two
* vertices.
* @param fromKey - search key of the originating vertex.
* @param toKey - search key of the destination vertex.
* @return true on success or false on failure.
*/
public boolean isReachable(E fromKey, E toKey)
{
ArrayList<Vertex> queue = new ArrayList<Vertex>();
E tmpKey = fromKey;
Edge tmpEdge;
Vertex tmp = first;
while (tmp != null)
{
if (tmp.data.equals(tmpKey))
{
tmpEdge = tmp.pEdge;
while (tmpEdge != null)
{
queue.add(tmpEdge.destination);
tmpEdge = tmpEdge.pNextEdge;
}
tmp = first;
tmpKey = queue.remove(0).data;
if (tmpKey.equals(toKey))
return true;
}
tmp = tmp.pNextVertex;
}
return false;
}
It works when a path between the two specified keys exists, but throws an index out of bounds error when there does not.
This is an adjacency list I traced for the sample data I have:
1 -> null
2 -> 1 -> 11 -> 12 -> null
3 -> 2 -> 4 -> null
4 -> null
5 -> 4 -> null
6 -> 5 -> 7 -> 13 -> 14 -> 15 -> null
7 -> 12 -> null
8 -> 7 -> 9 -> 10 -> 11 -> 12 -> null
9 -> 1 -> null
10 -> null
11 -> 1 -> 12 -> null
12 -> null
13 -> null
14 -> 2 -> 3 -> null
15 -> 3 -> 5 -> 14 -> null
When i call isReachable(5, 3)
, for instance, I get an index out of bounds exception. But if i call the method on (15, 2), it returns true.
I'm not really sure where to go from here. A friend suggested trying a BFS approach to the problem, but I didn't really follow his explanation. Am I on the right track? Any help is appreciated.
Upvotes: 1
Views: 565
Reputation: 742
This is a basic graph search algorithm, google "breadth first search" as a starting point. You need to keep track of nodes you've visited, which I don't see you having done yet.
Also, as I said in my comment, don't use an ArrayList
to maintain a queue, the remove
operation is slow, particularly removing the elements at the start of the array as you have to copy everything across by 1. Use a Queue
directly (https://docs.oracle.com/javase/7/docs/api/java/util/Queue.html)
Upvotes: 2