Data Structures for Java Data Structures for Java
William H. Ford William H. Ford William R. Topp William R. Topp
Chapter 26 Chapter 26
Implementing Graphs Implementing Graphs
Bret Ford
© 2005, Prentice Hall
Representing Graphs Representing Graphs
Adjacency matrix representation of a Adjacency matrix representation of a graph uses a matrix whose entries give graph uses a matrix whose entries give
the weight of an edge (v
the weight of an edge (v
ii,v ,v
jj) or 0 if there is ) or 0 if there is no edge from v
no edge from v
iito v to v
jj. .
Representing Graphs Representing Graphs
(concluded) (concluded)
An Adjacency list representation of a An Adjacency list representation of a
graph includes the vertex with the list of graph includes the vertex with the list of
its neighbors.
its neighbors.
DiGraph Components DiGraph Components
The Edge class holds data that references The Edge class holds data that references the destination of an edge and the weight the destination of an edge and the weight
of the edge.
of the edge.
Edge Class 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 Representing Vertex
Information Information
The VertexInfo class has a reference to the The VertexInfo class has a reference to the vertex value, the in-degree of the vertex, a vertex value, the in-degree of the vertex, a
list of edges originating at the vertex and list of edges originating at the vertex and
other information used by graph algorithms.
other information used by graph algorithms.
VertexInfo Class 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;
// indicates whether the object currently // represents a vertex
public boolean occupied;
VertexInfo Class VertexInfo Class
(continued) (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 VertexInfo Class
(concluded) (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 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 The Vertex Map and VertexInfo
ArrayList ArrayList
The vertex map contains key value pairs The vertex map contains key value pairs ‑ ‑ where the key is a reference to the vertex where the key is a reference to the vertex
and the value is an index into an ArrayList and the value is an index into an ArrayList
of VertexInfo objects.
of VertexInfo objects.
The Vertex Map and VertexInfo The Vertex Map and VertexInfo
ArrayList (concluded)
ArrayList (concluded)
Exploring the Adjacency List of Exploring the Adjacency List of
a Vertex a Vertex
A VertexInfo object allows access to all A VertexInfo object allows access to all the neighbors of the vertex.
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 Exploring the Adjacency List of
a Vertex (continued) a Vertex (continued)
Let us look at a code segment that scans Let us look at a code segment that scans the adjacency list looking for the edge of the adjacency list looking for the edge of
minimum weight. In order to output the minimum weight. In order to output the
edge, we must maintain the vInfo index of edge, we must maintain the vInfo index of
the destination vertex.
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 Exploring the Adjacency List of
a Vertex (continued) 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 Exploring the Adjacency List of
a Vertex (continued) 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 The occupied Field
Occupied field of a VertexInfo object Occupied field of a VertexInfo object
indicates if the object corresponds to an indicates if the object corresponds to an
existing vertex entry in the map.
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 DiGraph Class Design
The class provides an The class provides an availability stack availability stack to store to store indices for the ArrayList. Whenever a vertex is indices for the ArrayList. Whenever a vertex is
deleted from the map, push the index for the deleted from the map, push the index for the
corresponding vInfo element onto the stack.
corresponding vInfo element onto the stack.
When adding a new vertex, check to see When adding a new vertex, check to see
whether an index is available on the stack. If whether an index is available on the stack. If
so, pop it and reuse the corresponding vInfo so, pop it and reuse the corresponding vInfo
element to store vertex properties, thus element to store vertex properties, thus
insuring more efficient memory management.
insuring more efficient memory management.
DiGraph Class Design DiGraph Class Design
(continued)
(continued)
DiGraph Class Methods DiGraph Class Methods
The method getVInfoIndex() takes a The method getVInfoIndex() takes a vertex as an argument and returns the vertex as an argument and returns the
index of the corresponding element in the index of the corresponding element in the
ArrayList. The index is in the value field of ArrayList. The index is in the value field of
the vtxMap entry. A return value -1 the vtxMap entry. A return value -1
indicates that the vertex is not in the indicates that the vertex is not in the
graph. This method is used by many graph. This method is used by many
DiGraph class methods.
DiGraph class methods.
getVInfoIndex() getVInfoIndex()
// 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
Private method getVInfoIndex() looks Private method getVInfoIndex() looks up a vertex in the map and returns the up a vertex in the map and returns the
vInfo index of the vertex.
vInfo index of the vertex.
Getting Neighbors Getting Neighbors
The getNeighbors() method scans the The getNeighbors() method scans the
adjacency list of a vertex and returns a set adjacency list of a vertex and returns a set
containing its neighbors.
containing its neighbors.
getNeighbors() 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() getNeighbors()
(concluded) (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 Adding an Edge
To add an edge to a graph, obtain the To add an edge to a graph, obtain the
vInfo index of the source vertex and insert vInfo index of the source vertex and insert
an Edge object for the destination vertex an Edge object for the destination vertex
in the adjacency list. Update the in-degree in the adjacency list. Update the in-degree
of the destination vertex.
of the destination vertex.
Adding an Edge (continued) 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 Erasing a Vertex
To erase a vertex remove all of the edges To erase a vertex remove all of the edges to and from the vertex prior to erasing the to and from the vertex prior to erasing the
vertex itself.
vertex itself.
Erasing a Vertex (continued) 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 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.
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) Erasing a Vertex (continued)
Task 2: Delete all edges that terminate in Task 2: Delete all edges that terminate in v. These edges have the form (v
v. These edges have the form (v
ii, v) and , v) and are found by scanning all of the elements are found by scanning all of the elements
in vInfo. Extract the adjacency list for in vInfo. Extract the adjacency list for
each vertex and use an iterator to scan each vertex and use an iterator to scan
the element, removing the Edge object the element, removing the Edge object
that indicates v is an adjacent vertex.
that indicates v is an adjacent vertex.
Decrement of the variable numEdges with Decrement of the variable numEdges with
each edge deletion.
each edge deletion.
Erasing a Vertex (continued) 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) 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) Erasing a Vertex (continued)
Task 3: Delete all edges that emanate Task 3: Delete all edges that emanate from v. These edges constitute the
from v. These edges constitute the adjacency list for the vertex. First, adjacency list for the vertex. First,
determine the number of edges and determine the number of edges and
decrement numEdges. Then, search the decrement numEdges. Then, search the
list of Edge objects and decrement the in- list of Edge objects and decrement the in-
degree for each adjacent vertex. Delete degree for each adjacent vertex. Delete
each edge during the scan.
each edge during the scan.
Erasing a Vertex (concluded) 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--;
}
The running time for adding a vertex is The running time for adding a vertex is O(E) and for removing a vertex is
O(E) and for removing a vertex is O(V + E).
O(V + E).
Efficiency of addEdge() and Efficiency of addEdge() and
removeVertex() Methods
removeVertex() Methods
Graph Algorithm Support Graph Algorithm Support
Methods Methods
The DiGraph class includes access and The DiGraph class includes access and update methods for the color, data, and update methods for the color, data, and
parent reference properties of a vertex.
parent reference properties of a vertex.
The properties are found in the VertexInfo The properties are found in the VertexInfo
object corresponding to the vertex. The object corresponding to the vertex. The
implementations are relatively simple.
implementations are relatively simple.
Identify the object and access the Identify the object and access the
appropriate field.
appropriate field.
getColor() 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() 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) 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() 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 Graph Collection View
The method vertexSet() returns a set view The method vertexSet() returns a set view of the graph vertices. The implementation of the graph vertices. The implementation
of vertexSet() is similar to the of vertexSet() is similar to the
implementation for a set view of map keys implementation for a set view of map keys
or entries.
or entries.
Set view remove() Set view remove()
public boolean remove(Object item) {
boolean retValue = false;
if (vtxMap.containsKey(item)) {
removeVertex(item);
retValue = true;
}
return retValue;
}
DiGraph Iterators DiGraph Iterators
The implementation of the graph set view The implementation of the graph set view iterator uses an inner class IteratorImpl iterator uses an inner class IteratorImpl
similar to iterator implementations we similar to iterator implementations we
have discussed for the LinkedList and have discussed for the LinkedList and
other collections. The class includes a other collections. The class includes a
variable that is an iterator for the keySet variable that is an iterator for the keySet
collection view associated with the vertex
collection view associated with the vertex
map. map.
DiGraph Inner Class DiGraph Inner Class
IteratorImpl 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 DiGraph Inner Class
IteratorImpl (continued) 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 DiGraph Inner Class
IteratorImpl (concluded) 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);
} }