java - 如何调整 Dijkstra 算法以处理加权图

标签 java algorithm dijkstra

这段代码用于实现未加权图的 Dijkstra 算法。我应该更改什么才能使用加权图?我的图的边缘是双值,有机会在最短路径方法中使用泛型类型吗?

   /**
     * Determine the shortest path to all vertices from a vertex using Dijkstra's algorithm
     * To be called by public short method
     *
     * @param graph Graph object
     * @param sourceIdx Source vertex 
     * @param knownVertices previously discovered vertices
     * @param verticesIndex index of vertices in the minimum path
     * @param minDist minimum distances in the path
     *
     */
    private static <V> void shortestPath(AdjacencyMatrixGraph<V,Double> graph, int sourceIdx, boolean[] knownVertices, int[] verticesIndex, double [] minDist)  {  
        V vertexOrig = graph.vertices.get(sourceIdx);
        Queue<V> qaux = new LinkedList<V>();
        for(int i = 0; i < graph.numVertices; i++) {
            minDist[i] = 0;
            verticesIndex[i] = -1;
        }
        qaux.add(vertexOrig);
        while(!qaux.isEmpty()) {
            V vertex = qaux.remove();
            for (V vertexAdj: graph.directConnections(vertex)) {
                if(minDist[graph.toIndex(vertexAdj)] == 0) {
                    minDist[graph.toIndex(vertexAdj)] = minDist[graph.toIndex(vertex)] 
                            + graph.getEdge(vertex, vertexAdj);
                    verticesIndex[graph.toIndex(vertexAdj)] = graph.toIndex(vertex);
                    qaux.add(vertexAdj);
                } 
            }
        }
    }


    /**
     * Determine the shortest path between two vertices using Dijkstra's algorithm
     *
     * @param graph Graph object
     * @param source Source vertex 
     * @param dest Destination vertices
     * @param path Returns the vertices in the path (empty if no path)
     * @return minimum distance, -1 if vertices not in graph or no path
     *
     */
    public static <V> double shortestPath(AdjacencyMatrixGraph<V, Double> graph, V source, V dest, LinkedList<V> path){
        path.clear();
        if(!graph.checkVertex(source) || !graph.checkVertex(dest)) return -1;
        else if(source.equals(dest)) {
            path.add(dest);
            return 0;
        }
        double minDist[] = new double[graph.numVertices];
        int verticesIndex[] = new int[graph.numVertices];

        shortestPath(graph, graph.toIndex(source), new boolean[graph.numVertices]
        , verticesIndex, minDist);

        if(verticesIndex[graph.toIndex(source)] == -1 || verticesIndex[graph.toIndex(dest)] == -1) return -1;

        recreatePath(graph, graph.toIndex(source), graph.toIndex(dest), verticesIndex, path);
        Collections.reverse(path);
        System.out.println(path);
        System.out.println(minDist[graph.toIndex(dest)]);
        return minDist[graph.toIndex(dest)];
    }


    /**
     * Recreates the minimum path between two vertex, from the result of Dikstra's algorithm
     * 
     * @param graph Graph object
     * @param sourceIdx Source vertex 
     * @param destIdx Destination vertices
     * @param verticesIndex index of vertices in the minimum path
     * @param Queue Vertices in the path (empty if no path)
     */
    private static <V> void recreatePath(AdjacencyMatrixGraph<V, Double> graph, int sourceIdx, int destIdx, int[] verticesIndex, LinkedList<V> path){

        path.add(graph.vertices.get(destIdx));
        if (sourceIdx != destIdx){
            destIdx = verticesIndex[destIdx];        
            recreatePath(graph, sourceIdx, destIdx, verticesIndex, path);
        }
    }

最佳答案

Dijkstra 算法与加权图配合使用,计算图中从一个顶点到所有其他顶点的最短路径,前提是图中没有负边长度。因此无需更改 Dijkstra 的实现即可使其与加权图一起使用。如果它不适用于加权图,那么问题就出在 Dijkstra 的实现上。

如果图表未加权,您最好使用广度优先搜索,该搜索以线性时间运行来计算节点之间的距离。

Dijkstra 算法是一种贪婪算法,其工作原理是跟踪必须按其成本排序的顶点。即,下一个将被扩展的顶点是具有下一个最小成本的顶点。

对于 BFS,我们不需要这样做,因为所有边权重都是相同的。 Why use Dijkstra's Algorithm if Breadth First Search (BFS) can do the same thing faster?显示两者之间的差异

通过您的实现,我看到您正在使用队列来跟踪尚未探索的顶点。这并不能确保下一个扩展的顶点具有最小成本,因此您的算法将失败。

因此,每次您从队列中选择一个顶点进行扩展时,它应该是成本最小的顶点。这可以通过每次迭代Queue并以最小成本拾取顶点来实现,尽管这可能会将其减少到O(n^2)算法或使用堆数据结构,确保下一个选取的顶点始终是权重最小的顶点。

关于java - 如何调整 Dijkstra 算法以处理加权图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40709947/

相关文章:

algorithm - 从元素计算出堆的高度

java - 如何跳过同一行中插入的下一个变量?

algorithm - KMP 计数字符串出现次数

java - 此示例中的 token 有何用途?

java - Apache Wink 和 Apache CXF JAX-RS 实现

java - 快速 Activity 切换导致应用程序崩溃

algorithm - Dijkstra 算法修改

algorithm - 关于维基百科上 Dijkstra 算法实现的问题

algorithm - 图 - 顶点权重的最短路径

java - 查找 Java 代码中的所有数字文字