Using Existing Fibonacci Heap Java Implementation

2019-04-02 11:12发布

Using java programming language, I am trying to implement the most efficient shortest path algorithm on a graph with positive edge cost. To the best of my knowledge, that would be Dijkstra's algorithm with a Fibonacci Heap as the priority Queue. I borrowed the following Fibonacci Heap implementation by Keith Schwarz as stated in the link. http://keithschwarz.com/interesting/code/?dir=fibonacci-heap

In my code, I also modified the dijkstra algorithm implementation presented in this question,

Java: Using a Fibonacci Heap for Implementing Dijkstra's Algorithm

Here's my updated dijkstra based on my implementation,

public static void SPFibonacciHeap() {
    {

        FibonacciHeap<Node> myHeap = new FibonacciHeap<Node>();

        //adding all nodes to the PQ (heap)
        for(int i=0; i<nodeList.size(); i++)
                    myHeap.enqueue(nodeList.get(i), nodeList.get(i).d);

        while (!myHeap.isEmpty()) {

            //deque the minimum (first iteration will be the source)
            Entry<Node> u = myHeap.dequeueMin();


            // Visit each edge connected from u
            for (AdjacentNode a : u.getValue().adjacents) {

                //getting the adjacent node
                Node v = a.node;
                Entry<Node> vEntry = new Entry<Node>(v,v.d);//WRONG

                //getting the edge weight
                double weight = a.cost;

                double distanceThroughU = u.getValue().d + weight;
                if (distanceThroughU < v.d) {
                    v.d = distanceThroughU;
                    myHeap.decreaseKey(vEntry, v.d); //SHOWS ERROR
                    v.parent = u.getValue();
                }
            }
        }
    }
}

Here's my Node, and AdjacentNode classes,

class Node{

    Double [] label;
    double d; //node cost
    ArrayList<AdjacentNode> adjacents;
    Node parent;

    public Node(Double[] label, double d,ArrayList<AdjacentNode> adjacents)
    {
        this.label= label;
        this.d=d;
        this.adjacents=adjacents;
        parent=null;

    }




}


class AdjacentNode
{
    Node node;
    double cost;

    public AdjacentNode(Node node, double cost)
    {
        this.node= node;
        this.cost=cost;
    }
}

Everything went fine until i wanted to decrease the key in the following line,

myHeap.decreaseKey(vEntry, v.d); 

The problem I am facing is that vEntry should be an already existing node in the heap. However, I am not able to retrieve this node from the heap, since the only way I can think about to retrieve the adjacent node v is by using the adjacents list in the node u. But then, I incorrectly represent it as a new Entry Node in the following line,

Entry<Node> vEntry = new Entry<Node>(v,v.d);

This however would create a new Entry holding the node I am looking for, not the entry that exists in the heap with the node I am looking for. This results in Null pointer exception as expected.

I am not able to figure out the solution to this problem. Is it that getting a node entry which is adjacent to a given node entry seems not possible for this heap implementation? Can someone help? Thank you.

1条回答
别忘想泡老子
2楼-- · 2019-04-02 11:59

So... that's my code. :-) I figure I could probably help out here.

If you'll notice, the enqueue method returns back an Entry<T> representing the internal entry in the Fibonacci heap corresponding to the object you just enqueued. The intent is that, when you enqueue something into the Fibonacci heap, that you'll save the Entry<T> you get back somewhere so that you can then use it later. I actually also have an implementation of Dijkstra's algorithm up on my site. The way that I made this work was to store a second Map from nodes to Entry objects so that when I need to call decreaseKey, I can look up the Entry corresponding to the given node and then pass that into decreaseKey.

As a heads-up, while Dijkstra's algorithm with a Fibonacci heap is in theory faster than using something like a plain binary heap, in practice it tends to be a lot slower because the constant factors on the Fibonacci heap are so much higher. This is due to a number of factors (tons of pointer juggling, lots of linked structures with poor locality, etc.), so if your goal is to get the fastest possible wall-clock speed, you may want to just use a plain old binary heap. Even if you do want to go with a Fibonacci heap, you may want to try optimizing the implementation I've posted - I wrote it with the goal of correctness and clarity rather than raw efficiency.

查看更多
登录 后发表回答