【问题标题】:Dijkstra's algorithm java implementation bugDijkstra的算法java实现bug
【发布时间】:2014-06-23 11:00:52
【问题描述】:

所以首先这是硬件,所以不要马上给我答案,但我在编写 Dijstra 算法时遇到了麻烦。实验室让我们构建了一个优先队列,我已经制作并通过了给定的 JUnit 测试,所以我认为它是正确的。实验室的第二部分让我们在 dijstra 算法的实现中使用队列。这是我的 Dijkstra 代码

/**
 * Compute shortest paths in a graph.
 *
 * Your constructor should compute the actual shortest paths and
 * maintain all the information needed to reconstruct them.  The
 * returnPath() function should use this information to return the
 * appropriate path of edge ID's from the start to the given end.
 *
 * Note that the start and end ID's should be mapped to vertices using
 * the graph's get() function.
 */

class ShortestPaths {

    Multigraph graph;
    final int INF = Integer.MAX_VALUE;
    PriorityQueue<Integer> Q;
    int n;
    int dist[];
    Handle handles[];
    Edge edge[];

    /**
     * Constructor
     */
    public ShortestPaths(Multigraph G, int startId) {
        Q = new PriorityQueue<Integer>();
        graph = G;
        n = graph.nVertices();
        dist = new int [n];
        edge = new Edge [n];
        handles = new Handle[n];

        for (int i = 0; i<n; i++){
            dist[i] = INF;
        }
        dist[startId] = 0;

        Handle h = Q.insert(startId, dist[startId]);
        handles[startId] = h;   
        Q = new PriorityQueue<Integer>();
        while (!Q.isEmpty()){
            Vertex v = graph.get(Q.min());
            Q.extractMin();
            while (v.adj().hasNext()){
                relax(v.adj().next());  
            }       
        }   
    }

    private void relax(Edge e) {
        Handle h;
        int v = e.from().id();
        int w = e.to().id();
        if (dist[w] > dist[v] + e.weight()) {
            dist[w] = dist[v] + e.weight();
            edge[w] = e;
            if (handles[w].getIndex() != -1){
                Q.decreaseKey(handles[w], dist[w]);
            }
            else{
                h = Q.insert(w, dist[w]);
                handles[w] = h;
            }
        }
    }

    /**
     * Calculates the list of edge ID's forming a shortest path from the start
     * vertex to the specified end vertex.
     *
     * @return the array
     */
    public int[] returnPath(int endId) {
        int c = 0;
        int[] path = new int[edge.length];
        for (Edge e = edge[endId]; e != null; e = edge[e.from().id()]) {
            path[c] = e.id();
            c++;
        }
        return path;
    }


}

您知道,句柄只是一个对象,它存储关联的键值对的索引,这样我们以后可以找到它。句柄会自动更新,您可以在我的优先级队列中的交换过程中看到这一点。无论如何,问题是我的 edge[] 数组由于某种原因填充了 null,所以我不能返回任何路径。如何修复我的算法以正确更新 edge[]?任何帮助,将不胜感激。如果您想了解更多信息,请告诉我。此外,我还会发布 Vertex 和 Edge 类以供您查看。

【问题讨论】:

  • 你的问题到底是什么?
  • 我猜为什么我的 edge[] 数组为空,我该如何解决,抱歉没有说清楚让我编辑我的帖子
  • 这里有很多没人会读的代码。尝试使您的问题具体化,并仅显示代码的相关部分,最好不要超过您认为错误所在的 10-15 行代码。您还应该格式化问题,以便实际问题位于线程的第一个或最后一个,而不是隐藏在中间。
  • 您在哪里将边缘添加到边缘阵列?我看到了数组定义,但没有看到将边添加到数组的位置
  • 注意,PriorityQueue 的java实现支持减键操作,所以对Dijkstra几乎没用。

标签: java algorithm graph priority-queue dijkstra


【解决方案1】:

我注意到一个错误:

Q = new PriorityQueue<Integer>();
while (!Q.isEmpty()){ // <-- Q is always empty beсause of previous line

【讨论】:

  • 噢,是的愚蠢的错误。谢谢。不幸的是,现在我的句柄数组中有一个空指针。在第 61 行这里if(handles[w].getIndex() != -1)
  • 您可以尝试将if条件更改为if (handles[w] != null &amp;&amp; handles[w].getIndex() != -1){。那个时候'w'可能不在Q中。
  • 嗯,这很有趣。你说的有道理,但是代码中的变化产生了一个无限循环。嵌套的 while 循环更具体
  • 顶点迭代可能有问题。你可以试试这个:Vertex k=v.adj(); while(k.hasNext()) { relax(k); k=k.next(); }
  • well adj() 实际上返回了一个边缘迭代器,所以这不起作用。抱歉应该指定。如果需要,我可以添加顶点类的代码
猜你喜欢
  • 1970-01-01
  • 2019-04-02
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 2011-09-13
相关资源
最近更新 更多