package com.interview.graph;
import java.util.HashMap;
import java.util.Map;
/**
* Date 10/11/2014
* @author Tushar Roy
*
* Find single source shortest path using Dijkstra's algorithm
*
* Space complexity - O(E + V)
* Time complexity - O(ElogV)
*
* References
* https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
* CLRS book*/
public class DijkstraShortestPath {
public Map<Vertex<Integer>,Integer> shortestPath(Graph<Integer> graph, Vertex<Integer> sourceVertex){
//heap + map data structure
BinaryMinHeap<Vertex<Integer>> minHeap = new BinaryMinHeap<>();
//stores shortest distance from root to every vertex
Map<Vertex<Integer>,Integer> distance = new HashMap<>();
//stores parent of every vertex in shortest distance
Map<Vertex<Integer>, Vertex<Integer>> parent = new HashMap<>();
//initialize all vertex with infinite distance from source vertex
for(Vertex<Integer> vertex : graph.getAllVertex()){
minHeap.add(Integer.MAX_VALUE, vertex);
}
//set distance of source vertex to 0
minHeap.decrease(sourceVertex, 0);
//put it in map
distance.put(sourceVertex, 0);
//source vertex parent is null
parent.put(sourceVertex, null);
//iterate till heap is not empty
while(!minHeap.empty()){
//get the min value from heap node which has vertex and distance of that vertex from source vertex.
BinaryMinHeap<Vertex<Integer>>.Node heapNode = minHeap.extractMinNode();
Vertex<Integer> current = heapNode.key;
//update shortest distance of current vertex from source vertex
distance.put(current, heapNode.weight);
//iterate through all edges of current vertex
for(Edge<Integer> edge : current.getEdges()){
//get the adjacent vertex
Vertex<Integer> adjacent = getVertexForEdge(current, edge);
//if heap does not contain adjacent vertex means adjacent vertex already has shortest distance from source vertex
if(!minHeap.containsData(adjacent)){
continue;
}
//add distance of current vertex to edge weight to get distance of adjacent vertex from source vertex
//when it goes through current vertex
int newDistance = distance.get(current) + edge.getWeight();
//see if this above calculated distance is less than current distance stored for adjacent vertex from source vertex
if(minHeap.getWeight(adjacent) > newDistance) {
minHeap.decrease(adjacent, newDistance);
parent.put(adjacent, current);
}
}
}
return distance;
}
private Vertex<Integer> getVertexForEdge(Vertex<Integer> v, Edge<Integer> e){
return e.getVertex1().equals(v) ? e.getVertex2() : e.getVertex1();
}
public static void main(String args[]){
Graph<Integer> graph = new Graph<>(false);
/*graph.addEdge(0, 1, 4);
graph.addEdge(1, 2, 8);
graph.addEdge(2, 3, 7);
graph.addEdge(3, 4, 9);
graph.addEdge(4, 5, 10);
graph.addEdge(2, 5, 4);
graph.addEdge(1, 7, 11);
graph.addEdge(0, 7, 8);
graph.addEdge(2, 8, 2);
graph.addEdge(3, 5, 14);
graph.addEdge(5, 6, 2);
graph.addEdge(6, 8, 6);
graph.addEdge(6, 7, 1);
graph.addEdge(7, 8, 7);*/
graph.addEdge(1, 2, 5);
graph.addEdge(2, 3, 2);
graph.addEdge(1, 4, 9);
graph.addEdge(1, 5, 3);
graph.addEdge(5, 6, 2);
graph.addEdge(6, 4, 2);
graph.addEdge(3, 4, 3);
DijkstraShortestPath dsp = new DijkstraShortestPath();
Vertex<Integer> sourceVertex = graph.getVertex(1);
Map<Vertex<Integer>,Integer> distance = dsp.shortestPath(graph, sourceVertex);
System.out.print(distance);
}
}