当前位置: 首页 > 知识库问答 >
问题:

关于优先级队列的 Dijkstra 算法优化

李勇
2023-03-14

我在模拟中使用下面的代码。因为我一遍又一遍地调用dijkstra方法,性能对我来说非常关键。,我使用PriorityQueue将图的节点保持相对于它们到源的距离的升序。PriorityQueue为我提供了以O(log n)复杂度访问距离最小的节点。但是,要在重新计算节点距离后保持节点有序,我需要首先删除节点,而不是再次添加它。我想可能有更好的方法。我感谢任何反馈。提前感谢所有社区。

    public HashMap<INode, Double> getSingleSourceShortestDistance(INode sourceNode) {
    HashMap<INode, Double> distance = new HashMap<>();
    PriorityQueue<INode> pq;

   // The nodes are stored in a priority queue in which all nodes are sorted      

   according to their estimated distances.



    INode u = null;
    INode v = null;
    double alt;


    Set<INode> nodeset = nodes.keySet();
    Iterator<INode> iter = nodeset.iterator();
    //Mark all nodes with infinity
    while (iter.hasNext()) {
        INode node =  iter.next();
        distance.put(node, Double.POSITIVE_INFINITY);
        previous.put(node, null);
    }
    iter = null;

    // Mark the distance[source] as 0
    distance.put(sourceNode, 0d);


    pq = new PriorityQueue<>(this.network.getNodeCount(), new NodeComparator(distance));

    pq.addAll(nodeset);

    // Loop while q is empty
    while (!pq.isEmpty()) {
        // Fetch the node with the smallest estimated distance. 
        u = pq.peek();
        /**
         * break the loop if the distance is greater than the max net size.
         * That shows that the nodes in the queue can not be reached from
         * the source node.
         */
        if ((Double.isInfinite(distance.get(u).doubleValue()))) {

            break;
        }
        // Remove the node with the smallest estimated distance.
        pq.remove(u);

        // Iterate over all nodes (v) which are neighbors of node u
        iter = nodes.get(u).keySet().iterator();
        while (iter.hasNext()) {
            v = (INode) iter.next();
            alt = distance.get(u) + nodes.get(u).get(v).getDistance();
            if (alt < distance.get(v)) {
                distance.put(v, alt);
                //To reorder the queue node v is first removed and then inserted.
                pq.remove(v);
                pq.add(v);



            }
        }
    }



    return distance;



}

    protected static class NodeComparator<INode> implements Comparator<INode> {

    private Map<INode, Number> distances;

    protected NodeComparator(Map<INode, Number> distances) {
        this.distances = distances;
    }

    @Override
    public int compare(INode node1, INode node2) {
        return ((Double) distances.get(node1)).compareTo((Double) distances.get(node2));
    }
}

共有1个答案

邢昂然
2023-03-14

您可以使用具有increase_key和decrease_key实现的堆,因此可以更新节点距离,而无需删除并再次添加它。

 类似资料:
  • 我正在为Dikjstra算法做一个优先级队列。我目前在插入方法上有麻烦。我包含了整个类的代码,以防你需要更好地了解我想完成的事情。我将堆索引放在一个数组列表(heapIndex)中,堆放在另一个数组列表中。 那是我运行程序后的输出(值,优先级,堆索引)。*(-1)表示heapIndex中的空单元格。

  • 这是我写的Dijkstra算法的代码: 在这方面我不能理解的工作 这涉及到: < code>()运算符在这里有什么用?我是说它在这段代码中是如何运作的? 还有为什么我们使用

  • 在我实现Dijkstra算法的过程中,我有1个数组(包含所有节点)和1个优先级队列(包含所有节点)。每当一个节点排队时,我都会用新的距离和它来自哪里来更新所有相邻的节点,这样我就可以回溯路径。 优先级队列中的节点更新为新距离,数组中的节点更新为它来自的位置和新距离。当节点出列时,数组中的最终距离会更新: 用前一个节点的信息更新数组和用距离更新优先级队列是否可以接受? 只要找到更好的距离,就会发生这

  • 我的问题是:每个节点的优先级是什么?我认为它是最小值的传入边缘的权重,但我不确定。这是真的吗? 第二个问题,当我提取队列的根时,如果这个节点不与任何一个被访问的节点邻接,它将如何工作?

  • 有人能帮我找到我的PQ的问题吗?

  • 我正在使用优先级队列实现Dijkstra的算法,我想要一个函数从堆中删除一个元素,但我只能从Dijkstra的主节点索引中向它发送顶点索引,我找不到它在堆上的位置,我负担不起进行二进制搜索。有什么想法吗?