简体   繁体   中英

How to get path on Dijkstra Shortest Path

I have a graph implementation. My graph class is shown below:

public class Graph<V> {

private HashMap<V, ArrayList<Edge<V>>> adjacencyList;

/**
 * This list holds all the vertices so that we can iterate over them in the
 * toString function
 */
private ArrayList<V> vertexList;

private boolean directed;

public Graph(boolean isDirected) {
    directed = isDirected;
    adjacencyList = new HashMap<V, ArrayList<Edge<V>>>();
    vertexList = new ArrayList<V>();
} 
}

Also I have a method on my driver class which is to calculate shortest path from another vertice. It works quite fine and shows from one source vertice to all other vertices shortest path's weight:

public static <V> HashMap<V, ArrayList<Sehir>> dijkstraShortestPath(Graph<V> graph, V source, V son) {
    HashMap<V, Double> distances = new HashMap<V, Double>();

    HashMap<V, ArrayList<Sehir>> path = new HashMap<V, ArrayList<Sehir>>();//This is not working!

    //ArrayList<Sehir> arrList = new ArrayList<>();
    ArrayList<V> queue = new ArrayList<V>();
    ArrayList<V> visited = new ArrayList<V>();
    queue.add(0, source);
    distances.put(source, 0.0);
    path.put(source, new ArrayList<>());
    while (!queue.isEmpty()) {

        V currentVertex = queue.remove(queue.size() - 1);
        if(path.get(currentVertex)==null){
            path.put(currentVertex, new ArrayList<>());
        }


        // to save time we initialize all the distances to infinity as we go
        if (distances.get(currentVertex) == null) {
            distances.put(currentVertex, Double.POSITIVE_INFINITY);
        }
        // if(distances.get(currentVertex))
        for (V adjacentVertex : graph.getAdjacentVertices(currentVertex)) {

            if (distances.get(adjacentVertex) == null) {
                distances.put(adjacentVertex, Double.POSITIVE_INFINITY);
            }
            // if (!graph.getEdgeBetween(currentVertex,
            // adjacentVertex).isGidebilirMi()) {
            // // System.out.println(graph.getEdgeBetween(currentVertex,
            // // adjacentVertex).toString());
            // distances.put(adjacentVertex, Double.POSITIVE_INFINITY);
            // }

            // if the distance between the source and the adjacent vertex is
            // greater than the distance between the source and the current
            // vertex PLUS the weight between the current and adjacent
            // vertex, then we have found a shorter path than already
            // existed
            if (true) {

                if (distances.get(adjacentVertex) > graph.getDistanceBetween(currentVertex, adjacentVertex)
                        + distances.get(currentVertex)) {

                    distances.put(adjacentVertex,
                            graph.getDistanceBetween(currentVertex, adjacentVertex) + distances.get(currentVertex));

                    path.get(currentVertex).add((Sehir) adjacentVertex);
                }
            }

            if (!visited.contains(adjacentVertex) && !queue.contains(adjacentVertex)) {
                queue.add(0, adjacentVertex);
            }
        }
        visited.add(currentVertex);

    }
    // since the above statments only added the vertices as needed,
    // verticies that are completely unconnected to the source are not added
    // yet, so this adds them now
    for (V v : graph.getVertexList()) {
        if (!distances.containsKey(v)) {
            distances.put(v, Double.POSITIVE_INFINITY);
        }
    }

    return path;
}

Here, if I return distances , it works fine. But Path HashMap doesn't store right Information about path. How can I fix this? I want to get path, such as an object arrayList. By the way "Sehir" means "City" which is my objects on Graph.

Maybe this can help you

// Shortest path algorithm
//
// Algorithm to find distance from a given vertex, to each of the remaining
// Vertices
//
// Distance = 0...max - 1
//
for(each vertex, v) {
   if(V not visited AND V.Distance == Distance) {
       V is visited;
       for(each vertex w directly reachable from v) {
           if(w.dist == -1) {
              w.dist = dist + 1;
              w.prev = v;
           }
      }
   }
}

use following code (from http://www.baeldung.com/java-dijkstra )

1.define object to store graph

public class Graph {

    private Set<Node> nodes = new HashSet<>();

    public void addNode(Node nodeA) {
        nodes.add(nodeA);
    }

    // getters and setters 
}

2.define your node object

public class Node {

    private String name;

    private List<Node> shortestPath = new LinkedList<>();

    private Integer distance = Integer.MAX_VALUE;

    Map<Node, Integer> adjacentNodes = new HashMap<>();

    public void addDestination(Node destination, int distance) {
        adjacentNodes.put(destination, distance);
    }

    public Node(String name) {
        this.name = name;
    }

    // getters and setters
}

3.calculating shortest path from source:

public static Graph calculateShortestPathFromSource(Graph graph, Node source) {
    source.setDistance(0);

    Set<Node> settledNodes = new HashSet<>();
    Set<Node> unsettledNodes = new HashSet<>();

    unsettledNodes.add(source);

    while (unsettledNodes.size() != 0) {
        Node currentNode = getLowestDistanceNode(unsettledNodes);
        unsettledNodes.remove(currentNode);
        for (Entry < Node, Integer> adjacencyPair: 
          currentNode.getAdjacentNodes().entrySet()) {
            Node adjacentNode = adjacencyPair.getKey();
            Integer edgeWeight = adjacencyPair.getValue();
            if (!settledNodes.contains(adjacentNode)) {
                calculateMinimumDistance(adjacentNode, edgeWeight, currentNode);
                unsettledNodes.add(adjacentNode);
            }
        }
        settledNodes.add(currentNode);
    }
    return graph;
}

private static Node getLowestDistanceNode(Set < Node > unsettledNodes) {
    Node lowestDistanceNode = null;
    int lowestDistance = Integer.MAX_VALUE;
    for (Node node: unsettledNodes) {
        int nodeDistance = node.getDistance();
        if (nodeDistance < lowestDistance) {
            lowestDistance = nodeDistance;
            lowestDistanceNode = node;
        }
    }
    return lowestDistanceNode;
}

4.calculate shortest path:

private static void CalculateMinimumDistance(Node evaluationNode,
  Integer edgeWeigh, Node sourceNode) {
    Integer sourceDistance = sourceNode.getDistance();
    if (sourceDistance + edgeWeigh < evaluationNode.getDistance()) {
        evaluationNode.setDistance(sourceDistance + edgeWeigh);
        LinkedList<Node> shortestPath = new LinkedList<>(sourceNode.getShortestPath());
        shortestPath.add(sourceNode);
        evaluationNode.setShortestPath(shortestPath);
    }
}

test some scenario such as follow:

Node nodeA = new Node("A");
Node nodeB = new Node("B");
Node nodeC = new Node("C");
Node nodeD = new Node("D"); 
Node nodeE = new Node("E");
Node nodeF = new Node("F");

nodeA.addDestination(nodeB, 10);
nodeA.addDestination(nodeC, 15);

nodeB.addDestination(nodeD, 12);
nodeB.addDestination(nodeF, 15);

nodeC.addDestination(nodeE, 10);

nodeD.addDestination(nodeE, 2);
nodeD.addDestination(nodeF, 1);

nodeF.addDestination(nodeE, 5);

Graph graph = new Graph();

graph.addNode(nodeA);
graph.addNode(nodeB);
graph.addNode(nodeC);
graph.addNode(nodeD);
graph.addNode(nodeE);
graph.addNode(nodeF);

graph = Dijkstra.calculateShortestPathFromSource(graph, nodeA);

Also you can use this implementation: https://gist.github.com/gennad/791938

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM