简体   繁体   English

对Dijkstra算法的特定实现进行小的修改

[英]Small Modification to Particular Implementation of Dijkstra's Algorithm

Over the past few weeks I've been playing with a variety of implementations of Dijkstra's algorithm as part of a personal project (mainly to test performance). 在过去的几周中,作为个人项目的一部分,我一直在研究Dijkstra算法的各种实现(主要是为了测试性能)。 I have recently come across this implementation of the algorithm, which I have tested and everything. 我最近遇到了该算法的这种实现 ,我已经对其进行了测试以及所有测试。 However, I'm currently trying to modify that implementation so it takes an additional argument to represent the destination node, which means I want the algorithm to run only once from a specified source to a specified destination rather than to all other nodes in the graph. 但是,我目前正在尝试修改该实现,因此它需要一个附加参数来表示目标节点,这意味着我希望算法仅从指定源到指定目标运行一次,而不是对图中的所有其他节点运行一次。

I tried adding a third targetNode parameter but the dest variable found in the implementation is of type Entry<T> and my parameter was of type Node (a custom class I wrote), so I eventually got an incompatible types error message. 我尝试添加第三个targetNode参数,但是在实现中找到的dest变量的类型为Entry<T>而我的参数的类型为Node (我编写的自定义类),因此最终收到了不兼容的类型错误消息。

Is it possible to somehow make this modification? 是否可以以某种方式进行此修改? I did it easily with another implementation but I can't seem to figure it out for this one mainly due to the different types Node and Entry<T> . 我通过另一种实现方式轻松完成了该任务,但主要由于NodeEntry<T>类型不同,因此我似乎无法弄清楚。 It's not really a big deal but I would like to do it. 这不是什么大不了的事,但我想这样做。

Thanks! 谢谢!

EDIT: Here's what I did: 编辑:这是我所做的:

public static <Node> Map<Node, Double> dijkstraFibonacciHeap(DirectedGraph<Node> graph, Node source, Node target) {
    FibonacciHeap<Node> priorityQueue = new FibonacciHeap<>();  
    Map<Node, FibonacciHeap.Entry<Node>> entries = new HashMap<>();
    Map<Node, Double> result = new HashMap<>();

    for (Node node : graph) {
        entries.put(node, priorityQueue.enqueue(node, Double.POSITIVE_INFINITY));
    }


    priorityQueue.decreaseKey(entries.get(source), 0.0);

    while (!priorityQueue.isEmpty()) {

        FibonacciHeap.Entry<Node> curr = priorityQueue.dequeueMin();

        result.put(curr.getValue(), curr.getPriority());

        for (Map.Entry<Node, Double> arc : graph.edgesFrom(curr.getValue()).entrySet()) {

            if (result.containsKey(arc.getKey())) {
                continue;
            }

            double pathCost = curr.getPriority() + arc.getValue();

            // Error occurrs here. 
             target = entries.get(arc.getKey());
            if (pathCost < target.getPriority()) {
                priorityQueue.decreaseKey(target, pathCost);
            }
        } 
    }
    return result;
}

Dijkstra's algorithm works by finding shortest paths from the source node to every other node in the graph. Dijkstra的算法通过查找从源节点到图中每个其他节点的最短路径来工作。 You can terminate it early once it finds the shortest path to your target node, of course, but this doesn't necessarily lead to much of a speedup. 当然,您可以在找到目标节点的最短路径后尽早终止它,但这并不一定会导致加速。

The "meet-in-the-middle" trick can be useful if you're really trying to speed up shortest-path finding, though. 但是,如果您确实想加快最短路径的查找速度,“中间相遇”技巧将很有用。 You run shortest paths from the source simultaneously with shortest paths from the sink (treating every edge as its reverse); 您可以同时运行从源头开始的最短路径和从接收器到来点的最短路径(将每条边作为相反方向处理); once both searches have reached the same node, you can reconstruct a shortest source-to-target path. 一旦两个搜索都到达相同的节点,就可以重建最短的源到目标路径。

A* is another way to go if you have a good guess as to what your graph looks like. 如果您对图形的外观有了很好的猜测,则A *是另一种选择。

I should also point out that another really, really easy optimisation to this code is to stop wrapping everything in objects. 我还应该指出,对该代码的另一个非常非常简单的优化是停止将所有内容包装在对象中。 You're paying a lot, both in space and in speed, for wrapping double s in Double classes and whatever your Node s are in classes as well. Double类中包装double以及在类中包装任何Node ,您在空间和速度上都付出了很多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM