简体   繁体   中英

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). 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.

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> . 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. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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