Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Dijkstra's algorithm using min-heap but failed

I am trying to implement Dijkstra's Algorithm using min-heap in java but getting wrong output every time. Here i fount the same topic in C++. Below is my graph. Node A, which is green colored, is source and Node F, which is red colored, is destination. My objective is to find out the shortest path length from A to F.

This is my graph

Below is my code

public class Dijkstra {
    private static Heap heap = new Heap();
    private static int[][] graph;

    public Dijkstra() {
        graph = new int[6][6];
        /*
         * The graph value assignment is just for checking the code. node A is
         * referred as node 0, node B is referred as node 1 and so on. finally
         * node F is referred as node 5.
         */
        graph[0][0] = graph[0][1] = graph[0][3] = graph[0][4] = graph[0][5] = graph[1][0] = graph[1][1] = graph[1][4] = graph[1][5] = graph[2][2] = graph[2][5] = graph[3][0] = graph[3][3] = graph[4][0] = graph[4][1] = graph[4][4] = graph[5][0] = graph[5][1] = graph[5][2] = graph[5][5] = 0;
        graph[1][2] = graph[2][1] = graph[2][3] = graph[3][2] = graph[3][4] = graph[4][3] = graph[4][5] = graph[5][4] = 1;
        graph[1][3] = graph[3][1] = 3;
        graph[0][2] = graph[2][0] = 4;
        graph[2][4] = graph[4][2] = 5;
        graph[3][5] = graph[5][3] = 8;
    }

    public static void main(String[] args) {
        Dijkstra dij = new Dijkstra();
        // Source is node A (node 0) and destination is node F (node 5)
        System.out.println(dij.solve(6, 0, 5));
    }

    public int solve(int numOfNodes, int source, int dest) {
        heap.push(source, 0);
        while (!heap.isEmpty()) {
            int u = heap.pop();
            if (u == dest)
                return heap.cost[dest];
            for (int i = 0; i < numOfNodes; i++) {
                if (graph[u][i] >= 0)
                    heap.push(i, heap.cost[u] + graph[u][i]);
            }
        }
        return -1;
    }
}

class Heap {
    private int[] data;
    private int[] index;
    public int[] cost;
    private int size;

    public Heap() {
        data = new int[6];
        index = new int[6];
        cost = new int[6];

        for (int i = 0; i < 6; i++) {
            index[i] = -1;
            cost[i] = -1;
        }

        size = 0;
    }

    public boolean isEmpty() {
        return (size == 0);
    }

    private void shiftUp(int i) {
        int j;
        while (i > 0) {
            j = (i - 1) / 2;
            if (cost[data[i]] < cost[data[j]]) {
                // swap here
                int temp = index[data[i]];
                index[data[i]] = index[data[j]];
                index[data[j]] = temp;
                // swap here
                temp = data[i];
                data[i] = data[j];
                data[j] = temp;
                i = j;
            } else
                break;
        }
    }

    private void shiftDown(int i) {
        int j, k;
        while (2 * i + 1 < size) {
            j = 2 * i + 1;
            k = j + 1;
            if (k < size && cost[data[k]] < cost[data[j]]
                    && cost[data[k]] < cost[data[i]]) {
                // swap here
                int temp = index[data[k]];
                index[data[k]] = index[data[i]];
                index[data[i]] = temp;
                // swap here
                temp = data[k];
                data[k] = data[i];
                data[i] = temp;

                i = k;
            } else if (cost[data[j]] < cost[data[i]]) {
                // swap here
                int temp = index[data[j]];
                index[data[j]] = index[data[i]];
                index[data[i]] = temp;
                // swap here
                temp = data[j];
                data[j] = data[i];
                data[i] = temp;

                i = j;
            } else
                break;
        }
    }

    public int pop() {
        int res = data[0];
        data[0] = data[size - 1];
        index[data[0]] = 0;
        size--;
        shiftDown(0);
        return res;
    }

    public void push(int x, int c) {
        if (index[x] == -1) {
            cost[x] = c;
            data[size] = x;
            index[x] = size;
            size++;
            shiftUp(index[x]);
        } else {
            if (c < cost[x]) {
                cost[x] = c;
                shiftUp(index[x]);
                shiftDown(index[x]);
            }
        }
    }
}

While running this whole code, i am getting 0 as output but one can clearly tell the cost from node A to node F is 7 (4+1+1+1 = A-C-D-E-F). Where is the error?

like image 885
Ravi Joshi Avatar asked Apr 09 '12 16:04

Ravi Joshi


People also ask

What are cases where Dijkstra's algorithm fails?

Since Dijkstra follows a Greedy Approach, once a node is marked as visited it cannot be reconsidered even if there is another path with less cost or distance. This issue arises only if there exists a negative weight or edge in the graph.

What is the complexity of Dijkstra's algorithm using A min-heap implementation?

The time complexity of dijkstra's algorithm can be reduced to O((V+E)logV) using adjacency list representation of the graph and a min-heap to store the unvisited vertices, where E is the number of edges in the graph and V is the number of vertices in the graph.

Why did Dijkstra's algorithm fail?

It happens because, in each iteration, the algorithm only updates the answer for the nodes in the queue. So, Dijkstra's algorithm does not reconsider a node once it marks it as visited even if a shorter path exists than the previous one. Hence, Dijkstra's algorithm fails in graphs with negative edge weights.

Does Dijkstra use min-heap?

This means the running time for Dijkstra's algorithm using a binary min-heap as a priority queue is O((|E|+|V|)log|V|) . A directed graph is weakly connected if replacing all of its directed edges with undirected edges produces a connected undirected graph.


1 Answers

You test for an existing edge using graph[u][i] >= 0. But your graph is defined to have no edge for value zero. So you should change it to

if (graph[u][i] > 0) ...

inside method solve. Another possibility is to mark non-existing edges with a value of -1 in your matrix. This would then also allow for zero-cost edges.

like image 132
Howard Avatar answered Oct 03 '22 21:10

Howard