The path() method
The path() method
The path() method carries out the actual shortest-path algorithm. It uses the DistPar class and the Vertex class, which we saw in the mstw.java program (Listing 14.1). The path() method is a member of the Graph class, which we also saw in mstw.java in a somewhat different version.
The Shortest-Path Problem 699
public void path() // find all shortest paths { int startTree = 0; // start at vertex 0 vertexList[startTree].isInTree = true; nTree = 1; // put it in tree
// transfer row of distances from adjMat to sPath for(int j=0; j<nVerts; j++)
{ int tempDist = adjMat[startTree][j]; sPath[j] = new DistPar(startTree, tempDist); }
// until all vertices are in the tree while(nTree < nVerts)
{ int indexMin = getMin(); // get minimum from sPath int minDist = sPath[indexMin].distance;
if(minDist == INFINITY) // if all infinite { // or in tree, System.out.println(“There are unreachable vertices”); break; // sPath is complete }
else { // reset currentVert currentVert = indexMin; // to closest vert startToCurrent = sPath[indexMin].distance; // minimum distance from startTree is // to currentVert, and is startToCurrent }
// put current vertex in tree vertexList[currentVert].isInTree = true; nTree++; adjust_sPath(); // update sPath[] array } // end while(nTree<nVerts)
displayPaths(); // display sPath[] contents nTree = 0; // clear tree
for(int j=0; j<nVerts; j++) vertexList[j].isInTree = false;
700 CHAPTER 14 Weighted Graphs
The starting vertex is always at index 0 of the vertexList[] array. The first task in path() is to put this vertex into the tree. As the algorithm proceeds, we’ll be moving other vertices into the tree as well. The Vertex class contains a flag that indicates
whether a vertex object is in the tree. Putting a vertex in the tree consists of setting this flag and incrementing nTree , which counts how many vertices are in the tree.
Second, path() copies the distances from the appropriate row of the adjacency matrix to sPath[] . This is always row 0, because for simplicity we assume 0 is the index of
the starting vertex. Initially, the parent field of all the sPath[] entries is A, the start- ing vertex.
We now enter the main while loop of the algorithm. This loop terminates after all the vertices have been placed in the tree. There are basically three actions in this loop:
1. Choose the sPath[] entry with the minimum distance.
2. Put the corresponding vertex (the column head for this entry) in the tree. This becomes the “current vertex,” currentVert .
3. Update all the sPath[] entries to reflect distances from currentVert . If path() finds that the minimum distance is infinity, it knows that some vertices are
unreachable from the starting point. Why? Because not all the vertices are in the tree (the while loop hasn’t terminated), and yet there’s no way to get to these extra
vertices; if there were, there would be a non-infinite distance. Before returning, path() displays the final contents of sPath[] by calling the
displayPaths() method. This is the only output from the program. Also, path() sets nTree to 0 and removes the isInTree flags from all the vertices, in case they might be used again by another algorithm (although they aren’t in this program).
Finding the Minimum Distance with getMin() To find the sPath[] entry with the minimum distance, path() calls the getMin() method. This routine is straightforward; it steps across the sPath[] entries and returns with the column number (the array index) of the entry with the minimum distance.
public int getMin() // get entry from sPath { // with minimum distance int minDist = INFINITY; // assume large minimum int indexMin = 0; for(int j=1; j<nVerts; j++) // for each vertex,
{ // if it’s in tree and if( !vertexList[j].isInTree && // smaller than old one
The Shortest-Path Problem 701
{ minDist = sPath[j].distance; indexMin = j; // update minimum }
} // end for return indexMin; // return index of minimum } // end getMin()
We could have used a priority queue as the basis for the shortest-path algorithm, as we did in the previous section to find the minimum spanning tree. If we had, the getMin() method would not have been necessary; the minimum-weight edge would have appeared automatically at the front of the queue. However, the array approach shown makes it easier to see what’s going on.
Updating sPath[] with adjust_sPath() The adjust_sPath() method is used to update the sPath[] entries to reflect new infor- mation obtained from the vertex just inserted in the tree. When this routine is called, currentVert has just been placed in the tree, and startToCurrent is the current entry in sPath[] for this vertex. The adjust_sPath() method now examines each vertex entry in sPath[] , using the loop counter column to point to each vertex in turn. For each sPath[] entry, provided the vertex is not in the tree, it does three things:
1. It adds the distance to the current vertex (already calculated and now in startToCurrent ) to the edge distance from currentVert to the column vertex. We call the result startToFringe .
2. It compares startToFringe with the current entry in sPath[] .
3. If startToFringe is less, it replaces the entry in sPath[] . This is the heart of Dijkstra’s algorithm. It keeps sPath[] updated with the shortest
distances to all the vertices that are currently known. Here’s the code for adjust_sPath() :
public void adjust_sPath() { // adjust values in shortest-path array sPath int column = 1; // skip starting vertex while(column < nVerts) // go across columns
{ // if this column’s vertex already in tree, skip it if( vertexList[column].isInTree )
{ column++;
702 CHAPTER 14 Weighted Graphs
} // calculate distance for one sPath entry // get edge from currentVert to column int currentToFringe = adjMat[currentVert][column];
// add distance from start int startToFringe = startToCurrent + currentToFringe;
// get distance of current sPath entry int sPathDist = sPath[column].distance;
// compare distance from start with sPath entry if(startToFringe < sPathDist) // if shorter,
{ // update sPath sPath[column].parentVert = currentVert; sPath[column].distance = startToFringe; }
column++; } // end while(column < nVerts)
} // end adjust_sPath() The main() routine in the path.java program creates the tree of Figure 14.6 and
displays its shortest-path array. Here’s the code: public static void main(String[] args)
{ Graph theGraph = new Graph(); theGraph.addVertex(‘A’); // 0 (start) theGraph.addVertex(‘B’); // 1 theGraph.addVertex(‘C’); // 2 theGraph.addVertex(‘D’); // 3 theGraph.addVertex(‘E’); // 4
theGraph.addEdge(0, 1, 50); // AB 50 theGraph.addEdge(0, 3, 80); // AD 80 theGraph.addEdge(1, 2, 60); // BC 60 theGraph.addEdge(1, 3, 90); // BD 90 theGraph.addEdge(2, 4, 40); // CE 40 theGraph.addEdge(3, 2, 20); // DC 20 theGraph.addEdge(3, 4, 70); // DE 70 theGraph.addEdge(4, 1, 50); // EB 50
System.out.println(“Shortest paths”); theGraph.path(); // shortest paths System.out.println();
The Shortest-Path Problem 703
The output of this program is A=inf(A) B=50(A) C=100(D) D=80(A) E=140(C)