📄 shortestpathdijkstraalgorithm.java
字号:
package salvo.jesus.graph.algorithm;import salvo.jesus.graph.*;import salvo.jesus.util.*;import java.util.*;/** * A concrete implementation of ShortestPathAlgorithm using Dijkstra's method. * * @author Jesus M. Salvo Jr. */public class ShortestPathDijkstraAlgorithm extends ShortestPathAlgorithm { /** * List of vertices that has been added to the tree */ private List visited; /** * Heap of FringeObjects that are to be processed. */ private Heap fringe; /** * Subgraph forming the shortest spanning tree. */ private WeightedGraph shortestpathtree; /** * Comparator used to be compare priorities in the fringe. */ private HeapNodeComparator comparator; /** * Creates an instance of ShortestPathDijkstraAlgorithm. * * @param wgraph The WeightedGraph where a shortest path spanning tree will be determined. * @param comparator The HeapNodeComparator to be used to compare priorities of objects in the fringe/heap. */ public ShortestPathDijkstraAlgorithm( WeightedGraph wgraph, HeapNodeComparator comparator ) { super( wgraph ); this.visited = new ArrayList( 10 ); this.comparator = comparator; this.fringe = new Heap( new HeapNodeComparator( 1 )); } /** * Determines the shortest path from a given vertex to all other vertices * that are in the same connected set as the given vertex in the weighted graph * using Dijkstra's algorithm. * * @return A WeightedGraph comprising of the shortest path spanning tree. * @param from The Vertex from where we want to obtain the shortest path * to all other vertices. */ public WeightedGraph shortestPath( Vertex from ) { // clear the graph. // this.shortestpathtree.clear(); this.shortestpathtree = new WeightedGraphImpl(); // Now add the vertex we are interested in to the fringe. this.fringe.insert( new HeapNode( new FringeObject( from, null ), 0.0 )); // Continually process while there are vertices in the heap. while( !this.fringe.isEmpty() ) { // Moves the highest priority node from the heap to the tree. this.moveToVisited(); } // Clear the vectors this.visited.clear(); this.fringe.clear(); return shortestpathtree; } /** * Moves the vertex that has the highest priority in the heap * from the fringe to the tree, */ private void moveToVisited() { HeapNode prioritynode; // Remove the node with highest priority from the fringe ... prioritynode = this.fringe.remove( ); FringeObject fringeobject = (FringeObject) prioritynode.getObject(); Vertex priorityvertex = fringeobject.vertex; // ... and add it to the tree. this.visited.add( priorityvertex ); if( fringeobject.edge != null ) { try { this.shortestpathtree.addEdge( fringeobject.edge ); } catch( Exception ex ) { ex.printStackTrace(); } } // ... then move all the adjacent vertices of the vertex // we just moved to the tree and put them in the fringe. this.moveAdjacentVerticesToFringe( prioritynode ); } /** * Gets all the adjacent vertices from unseen to the fringe. * The parameter vertex must be a vertex that is being moved * from the fringe to the tree. This method must only be called * by the method moveToVisited(). * * @param vertex The vertex that is being moved from the fringe to the tree * and whose adjacent vertices we want added to the fringe. */ private void moveAdjacentVerticesToFringe( HeapNode prioritynode ) { // Get the vertex encapsulated by the heap node Vertex priorityvertex = ((FringeObject) prioritynode.getObject()).vertex; // Then get the edges of the vertex // We cant use wgraph.getAdjacentVertices() as that will // not tell us what edge to use. List incidentedges = this.wgraph.getEdges( priorityvertex ); // Get the priority of the heap node double priority = prioritynode.getPriority(); // We need to iterate through the edges Iterator iterator = incidentedges.iterator(); // Because we are using HeapNodes in the fringe, // we need a way to compare the object (a Vertex) encapsulated in a HeapNode in the // fringe and a Vertex HeapNodeObjectComparator heapnodeobjectcomparator = new HeapNodeObjectComparator(); // The current incident edge iterated WeightedEdge incidentedge; // The current adjacent vertex within the iteration Vertex adjacentvertex; // Either an existing HeapNode or an exsting one in the fringe HeapNode heapnode; // The new priority of a heapnode double fringepriority; // For each edge of the vertex ... while( iterator.hasNext() ) { incidentedge = (WeightedEdge) iterator.next(); // ... get the vertex opposite to the priority vertex // meaning get the adjacent vertex adjacentvertex = incidentedge.getOppositeVertex( priorityvertex ); // ... check if the adjacent vertex has been visited // If it has been visited, then proceed with the next edge if( this.visited.contains( adjacentvertex )) continue; // ... check if the adjacent vertex is already in the fringe heapnode = (HeapNode) this.fringe.contains( adjacentvertex, heapnodeobjectcomparator ); // ... if it is not yet on the fringe, add it to the fringe if( heapnode == null ) { fringepriority = priority + incidentedge.getWeight(); heapnode = new HeapNode( new FringeObject( adjacentvertex, incidentedge ), fringepriority ); this.fringe.insert( heapnode ); } // If it is already the fringe, reassign its priority, // only if it will give it a "higher" priority. // Use the HeapNodeComparator to determine which is "higher". else { fringepriority = priority + incidentedge.getWeight(); if( this.comparator.compare( new HeapNode( adjacentvertex, fringepriority), heapnode ) < 0 ) { this.fringe.setPriority( heapnode, fringepriority ); // Also reassign the edge that is used to get the shortest path FringeObject fobject = (FringeObject) heapnode.getObject(); fobject.edge = incidentedge; } } } }}/** * A Comparator for comparing the Vertex in the FringObject of the HeapNode * against another Vertex. */class HeapNodeObjectComparator implements Comparator { /** * Compare a Vertex against the Vertex in the FringeObject of a HeapNode. * The comparison is made using the == operator to compare the actual instance. * * @return Returns 0 if they are the same object. Returns -1 otherwise. */ public int compare( Object vertex, Object hnode ) { Vertex compareTo = (Vertex) vertex; HeapNode heapnode = (HeapNode) hnode; FringeObject fringeobject = (FringeObject) heapnode.getObject(); Vertex heapobject = (Vertex) fringeobject.vertex; if( compareTo == heapobject ) return 0; else return -1; }}/** * An Object encapsulated in a HeapNode, which in turn is added to the fringe. * The classical algorithm only mentions of storing vertices in the fringe, but * it is programatically difficult to determine what edge to add to the * shortest path spanning tree when moving a vertex from the fringe to the tree. * It is therefore easier to store the edge along with the vertex in the fringe. * * The edge stored along with the vertex in the fringe is the * edge connecting the vertex that has been moved from the fringe to the tree * and the vertex adjacent to the vertex that has been moved from the fringe * and being added to the fringe. Got that? * */class FringeObject { Vertex vertex; WeightedEdge edge; public FringeObject( Vertex vertex, WeightedEdge edge ) { this.vertex = vertex; this.edge = edge; } public String toString() { return "Vertex: " + vertex + "; Edge: " + edge; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -