Data Structures for Java
William H. Ford William R. Topp
Chapter 26
Implementing Graphs
Bret Ford
© 2005, Prentice Hall
Representing Graphs
• Adjacency matrix representation of a graph
uses a matrix whose entries give the weight of
an edge (v
i,v
j) or 0 if there is no edge from v
ito
v
j.
Representing Graphs (concluded)
• An Adjacency list representation of a graph includes the vertex with the list of its
neighbors.
DiGraph Components
• The Edge class holds data that references the
destination of an edge and the weight of the
edge.
Edge Class
class Edge {
// index of the destination vertex in the ArrayList // vInfo of vertex properties
public int dest;
// weight of this edge public int weight;
public Edge(int dest, int weight) {
this.dest = dest;
this.weight = weight;
}
public boolean equals(Object obj) {
return ((Edge)obj).dest == this.dest;
} }
Representing Vertex Information
• The VertexInfo class has a reference to the
vertex value, the in-degree of the vertex, a list
of edges originating at the vertex and other
information used by graph algorithms.
VertexInfo Class
// maintains vertex properties, including // its set of Edges
class VertexInfo<T>
{
// vertex reference back to the vertex in the map public T vertex;
// list of Edge objects (adjacent vertices) for the // current vertex
public LinkedList<Edge> edgeList;
// maintains the in-degree of the vertex public int inDegree;
public int outDegree;
// indicates whether the object currently // represents a vertex
public boolean occupied;
VertexInfo Class (continued)
// indicates vertex color for use in algorithms // that traverse the vertices of a Graph
public VertexColor color;
// available to algorithms for storing relevant // data values
public int dataValue;
// available to Graph algorithms; holds parent // which is a vertex that has an edge terminating // in the current vertex
public T parent;
VertexInfo Class (concluded)
// constructor creates an object with initial // values for the vertex, edgeList, inDegree, // and occupied fields
public VertexInfo(T v) {
vertex = v;
edgeList = new LinkedList<Edge>();
inDegree = 0;
occupied = true;
} }
VertexColor Class
public enum VertexColor {
WHITE, GRAY, BLACK }
The VertexColor class maintains the color of a vertex.
The VertexColor class maintains the color of a vertex.
The colors of WHITE, GRAY, and BLACK are values of the The colors of WHITE, GRAY, and BLACK are values of the
enumerated type.
enumerated type.
The Vertex Map and VertexInfo ArrayList
• The vertex map contains key value pairs ‑
where the key is a reference to the vertex and the value is an index into an ArrayList of
VertexInfo objects.
The Vertex Map and VertexInfo
ArrayList (concluded)
Exploring the Adjacency List of a Vertex
• A VertexInfo object allows access to all the neighbors of the vertex.
VertexInfo<T> vtxInfo = vInfo.get(i);
// declare an iterator for edgeList and position it at the first // element in the adjacency list
Iterator<Edge> iter = vtxInfo.edgeList.iterator();
// extract the first element and output its weight Edge e = iter.next();
System.out.println(e.weight);
// use the dest field to access the vInfo element that corresponds // to the adjacent vertex; the index of the element is e.dest;
// output the name of the vertex
VertexInfo<T> edgeVtxInfo = vInfo.get(e.dest);
System.out.println(edgeVtxInfo.vertex);
Exploring the Adjacency List of a Vertex (continued)
• Let us look at a code segment that scans the adjacency list looking for the edge of
minimum weight. In order to output the edge, we must maintain the vInfo index of the
destination vertex.
// declare variables for the minimum dest index and // minimum weight
int minDest, minWeight = Integer.MAX_VALUE;
// VertexInfo objects for elements in ArrayList vInfo;
// current vertex element in vInfo is vtxInfo; vInfo element // for a neighbor is edgeVtxInfo
VertexInfo<T> vtxInfo = null, edgeVtxInfo = null;
...
Exploring the Adjacency List of a Vertex (continued)
// iterator to scan adjacency list for current vertex Iterator<Edge> iter = vtxInfo.edgeList.iterator();
while (iter.hasNext) {
// extract next element (Edge object) from adjacency list Edge e = iter.next();
// update if new minimum weight is discovered if (e.weight < minWeight)
{
minWeight = e.weight;
minDest = e.dest;
} }
Exploring the Adjacency List of a Vertex (continued)
// output the edge that has minimum weight; first get the
// corresponding vInfo element and then access the vertex field edgeVtxInfo = vInfo.get(minDest);
System.out.println("Edge (" + vtxInfo.vertex + ", " +
edgeVtxInfo.vertex + ") has weight + edgeVtxInfo.weight);
The occupied Field
• Occupied field of a VertexInfo object indicates if the object corresponds to an existing vertex entry in the map.
for (i = 0; i < vInfo.size(); i++) {
VertexInfo<T> vtxInfo = vInfo.get(i);
if (vtxInfo.occupied)
< vInfo element corresponds to an actual vertex>
}
DiGraph Class Design
• The class provides an availability stack to store indices for the ArrayList. Whenever a vertex is deleted from the map, push the index for the corresponding vInfo element onto the stack.
When adding a new vertex, check to see
whether an index is available on the stack. If so, pop it and reuse the corresponding vInfo element to store vertex properties, thus
insuring more efficient memory management.
DiGraph Class Design (continued)
DiGraph Class Methods
• The method getVInfoIndex() takes a vertex as an argument and returns the index of the
corresponding element in the ArrayList. The index is in the value field of the vtxMap entry.
A return value -1 indicates that the vertex is
not in the graph. This method is used by many
DiGraph class methods.
getVInfoIndex()
• Private method getVInfoIndex() looks
up a vertex in the map and returns the vInfo index of the vertex.
// takes vertex v in the map and returns the // index of the corresponding vInfo element // or -1 if v is not a vertex
private int getVInfoIndex(Object v) {
// get the Integer value field of the vtxMap entry Integer indexObj = vtxMap.get(v);
// if value is null, there is not entry in // the map; return -1; otherwise, convert // object to an int
if (indexObj == null) return -1;
else
Getting Neighbors
• The getNeighbors() method scans the
adjacency list of a vertex and returns a set
containing its neighbors.
getNeighbors()
// returns the vertices that are adjacent to
// vertex v in a Set object; if v is not a graph // vertex, throws IllegalArgumentException
public Set<T> getNeighbors(T v) {
// find the VertexInfo object for index v int index = getVInfoIndex(v);
// check for an error and throw exception // if vertices not in graph
if (index == -1)
throw new IllegalArgumentException(
"DiGraph getNeighbors(): vertex not in graph");
getNeighbors() (concluded)
// create HashSet object to hold vertices,
// obtain the VertexInfo object, and initialize // an iterator to scan the adjacency list of // the VertexInfo object
HashSet<T> edgeSet = new HashSet<T>();
VertexInfo<T> vtxInfo = vInfo.get(index);
Iterator<Edge> iter = vtxInfo.edgeList.iterator();
Edge e = null;
while (iter.hasNext()) {
e = iter.next();
edgeSet.add(vInfo.get(e.dest).vertex);
}
return edgeSet;
}
Adding an Edge
• To add an edge to a graph, obtain the vInfo index of the source vertex and insert an Edge object for the destination vertex in the
adjacency list. Update the in-degree of the
destination vertex.
Adding an Edge (continued)
pos1=getVInfoIndex(v1);
pos2=getVInfoIndex(v2);
// get VertexInfo objects for vertices v1 and v2 VertexInfo<T> vtxInfo1 = vInfo.get(pos1),
vtxInfo2 = vInfo.get(pos2);
Edge e = new Edge(pos2, w);
boolean returnValue = true;
// try to add an Edge reference v1-v2.
// if it already exists, just return if (!vtxInfo1.edgeList.contains(e)) {
vtxInfo1.edgeList.add(e);
// increment inDegree for vertex v2 and number of edges vtxInfo2.inDegree++;
numEdges++;
} else
returnValue = false;
return returnValue;
Erasing a Vertex
• To erase a vertex remove all of the edges to
and from the vertex prior to erasing the vertex
itself.
Erasing a Vertex (continued)
• Task 1: Get the VertexInfo object in vInfo that corresponds to the index. Set the occupied field to false and then push the index onto an availability stack for use by a vertex that might be added later.
// iterator used to scan Edge objects in adjacency lists Iterator<Edge> iter = null;
Edge e = null;
VertexInfo<T> vtxInfo = vInfo.get(index), edgeVtxInfo;
vtxInfo.occupied = false;
availStack.push(index);
Erasing a Vertex (continued)
• Task 2: Delete all edges that terminate in v.
These edges have the form (v
i, v) and are
found by scanning all of the elements in vInfo.
Extract the adjacency list for each vertex and
use an iterator to scan the element, removing
the Edge object that indicates v is an adjacent
vertex. Decrement of the variable numEdges
with each edge deletion.
Erasing a Vertex (continued)
// remove all the edges that terminate at the vertex being // removed. use a loop to check all of the VertexInfo
// elements in vInfo for which occupied is true; these // correspond to actual vertices in the map
for (int i = 0; i < vInfo.size(); i++) {
// get the VertexInfo object for index i edgeVtxInfo = vInfo.get(i);
Erasing a Vertex (continued)
// check if vertex is valid if (edgeVtxInfo.occupied) {
// obtain an iterator to scan the adjacency list iter = edgeVtxInfo.edgeList.iterator();
while (iter.hasNext()) {
// get the Edge object and check if the dest field // has value index which identifies vertex v; if so // remove it and decrement numEdges
e = iter.next();
if (e.dest == index) {
iter.remove();
numEdges--;
break;
} }
}
Erasing a Vertex (continued)
• Task 3: Delete all edges that emanate from v.
These edges constitute the adjacency list for the vertex. First, determine the number of
edges and decrement numEdges. Then, search
the list of Edge objects and decrement the in-
degree for each adjacent vertex. Delete each
edge during the scan.
Erasing a Vertex (concluded)
// reduce numEdges by number of elements in adjacency list numEdges -= vtxInfo.edgeList.size();
// scan the adjacency list for vertex v and decrement the // in-degree for each adjacent vertex
iter = vtxInfo.edgeList.iterator();
while (iter.hasNext()) {
e = iter.next();
edgeVtxInfo = vInfo.get(e.dest);
iter.remove();
edgeVtxInfo.inDegree--;
}
Efficiency of addEdge() and removeVertex() Methods
• The running time for adding a vertex is O(E) and for removing a vertex is
O(V + E).
Graph Algorithm Support Methods
• The DiGraph class includes access and update methods for the color, data, and parent
reference properties of a vertex. The
properties are found in the VertexInfo object corresponding to the vertex. The
implementations are relatively simple.
Identify the object and access the appropriate
field.
getColor()
// returns the color of vertex v; if v is not
// a graph vertex, throws IllegalArgumentException;
// for use by graph algorithms public VertexColor getColor(T v) {
// find the vInfo index for v int pos = getVInfoIndex(v);
if (pos != -1)
return vInfo.get(pos).color;
else
// throw an exception
throw new IllegalArgumentException(
"DiGraph getColor(): vertex not in graph");
}
setParent()
// assigns the parent of vertex v to be p and returns // the previous parent; if v or p is not a graph
// vertex, throws IllegalArgumentException; for use // by graph algorithms
public T setParent(T v, T p) {
// find the vInfo index for v
int pos1 = getVInfoIndex(v), pos2 = getVInfoIndex(p);
VertexInfo<T> vtxInfo;
T oldParent = null;
setParent() (concluded)
if (pos1 != -1 && pos2 != -1) {
vtxInfo = vInfo.get(pos1);
oldParent = vtxInfo.parent;
vtxInfo.parent = p;
} else
// throw an exception
throw new IllegalArgumentException(
"DiGraph setParent(): vertex not in graph");
return oldParent;
}
colorWhite()
// sets the color of each vertex to VertexColor.WHITE;
// for use by graph algorithms public void colorWhite()
{
VertexInfo<T> vtxInfo;
for (int i = 0; i < vInfo.size(); i++) {
vtxInfo = vInfo.get(i);
if (vtxInfo.occupied)
vtxInfo.color = VertexColor.WHITE;
} }
Graph Collection View
• The method vertexSet() returns a set view of
the graph vertices. The implementation of
vertexSet() is similar to the implementation
for a set view of map keys or entries.
Set view remove()
public boolean remove(Object item) {
boolean retValue = false;
if (vtxMap.containsKey(item)) {
removeVertex(item);
retValue = true;
}
return retValue;
}
DiGraph Iterators
• The implementation of the graph set view
iterator uses an inner class IteratorImpl similar
to iterator implementations we have discussed
for the LinkedList and other collections. The
class includes a variable that is an iterator for
the keySet collection view associated with the
vertex map.
DiGraph Inner Class IteratorImpl
// implements graph iterators
private class IteratorImpl implements Iterator<T>
{
Iterator<T> iter;
T lastValue = null;
public IteratorImpl() {
// iter traverses the map vertices iter = vtxMap.keySet().iterator();
}
public boolean hasNext() {
return iter.hasNext();
}
DiGraph Inner Class
IteratorImpl (continued)
public T next() {
lastValue = iter.next();
return lastValue;
}
public void remove() {
if (lastValue == null)
throw new IllegalStateException(
"Graph vertex set iterator call " + "to next() required before calling " + "remove()");
DiGraph Inner Class
IteratorImpl (concluded)
// find the index of lastValue in vInfo int index = getVInfoIndex(lastValue);
// remove the current vertex from the map iter.remove();
// remove all edges that terminate at // lastValue, and update the in-degree // of each neighbor of lastValue
removeFixup(index);
} }