【问题标题】:How to get path on Dijkstra Shortest Path如何在 Dijkstra 最短路径上获取路径
【发布时间】:2018-03-03 17:24:24
【问题描述】:

我有一个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;
}

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

【问题讨论】:

    标签: java algorithm graph shortest-path dijkstra


    【解决方案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

    【讨论】:

    • 感谢您的帮助。但是,我的实现是必需的。那么,如何将这种 ArrayList 添加到我的图表中?再次感谢
    • Graph 变量和类不会改变任何东西,可以删除。您可以从变量 shortestPath 中获取最短路径。
    【解决方案2】:

    也许这对你有帮助

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

    【讨论】:

    • 谢谢,但在我的实现中我不知道如何实现,因为我不知道我是否保留以前的顶点
    猜你喜欢
    • 2014-08-07
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多