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.
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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With