package se.chalmers.cs.gf.graph; import java.util.*; import java.io.*; /** * Uses Dijkstras shortest-path algorithm to find a shortest path * in a graph. */ public class DijkstraPath { private Graph graph; public DijkstraPath(Graph graph) { this.graph = graph.copyChangeNodeValues(null); } /** * Find the shortest path between two nodes in the graph. */ public Path computePath(String fromName, String toName) { // reset all node data for (Graph.Node node : graph.nodes()) node.setValue(new NodeData()); Graph.Node from = graph.getNode(fromName); from.getValue().dist = 0.0; PriorityQueue.Node> q = HeapPriorityQueue.create(); q.insertItem(0.0, from); int nodesLeft = graph.countNodes(); while (!q.isEmpty() && nodesLeft > 0) { Graph.Node u = q.removeMin(); NodeData uData = u.getValue(); if (!uData.visited) { uData.visited = true; nodesLeft--; for (Graph.Edge edge : u.adjacent()) { Graph.Node to = edge.getTo(); NodeData toData = to.getValue(); double newDist = uData.dist + edge.getWeight(); if (newDist < toData.dist) { toData.dist = newDist; toData.prev = edge; q.insertItem(newDist, to); } } } } List.Edge> pathEdges = edgesTo(graph.getNode(toName)); return edgesToPath(pathEdges); } /** * Get the list of edges going from the start node to the given node. */ private List.Edge> edgesTo(Graph.Node node) { LinkedList.Edge> edges = new LinkedList.Edge>(); Graph.Edge e = node.getValue().prev; while (e != null) { edges.addFirst(e); e = e.getFrom().getValue().prev; } return edges; } /** * Take a list of edges and make a Path. */ private Path edgesToPath(List.Edge> edges) { Path path = new Path(); for (Graph.Edge e : edges) path.addLeg(e.getFrom().getKey(), e.getTo().getKey(), e.getWeight(), e.getValue()); return path; } private static class NodeData { public double dist = Double.POSITIVE_INFINITY; public Graph.Edge prev = null; public boolean visited = false; } }