如何在Dijkstra最短路径上获得路径

时间:2018-03-03 08:22:04

标签: java algorithm graph shortest-path dijkstra

我有一个graph实现。我的图表类如下所示:

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>();
} 
}

此外,我的驱动程序类上有一个方法,用于计算来自另一个顶点的最短路径。它工作得很好,并从一个源顶点到所有其他顶点显示最短路径的权重:

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;
}

在这里,如果我返回距离,它可以正常工作。但路径 HashMap不存储有关路径的正确信息。我怎样才能解决这个问题?我想获取路径,例如对象arrayList。顺便说一句,“Sehir”的意思是“城市”,这是我在Graph上的对象。

2 个答案:

答案 0 :(得分:1)

也许这可以帮到你

// 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;
           }
      }
   }
}

答案 1 :(得分:1)

使用以下代码(来自http://www.baeldung.com/java-dijkstra

1.定义存储图形的对象

public class Graph {

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

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

    // getters and setters 
}

2.定义节点对象

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.计算来自源头的最短路径:

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.计算最短路径:

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);
    }
}

测试一些场景,例如:

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);

您也可以使用此实现:https://gist.github.com/gennad/791938