package com.interview.graph;
import java.util.*;
/**
* Date 10/11/2014
* @author Tushar Roy
*
* Find minimum spanning tree using Prim's algorithm
*
* Space complexity - O(E + V)
* Time complexity - O(ElogV)
*
* References
* https://en.wikipedia.org/wiki/Prim%27s_algorithm
* CLRS book
*/
public class PrimMST {
/**
* Main method of Prim's algorithm.
*/
public List<Edge<Integer>> primMST(Graph<Integer> graph){
//binary heap + map data structure
BinaryMinHeap<Vertex<Integer>> minHeap = new BinaryMinHeap<>();
//map of vertex to edge which gave minimum weight to this vertex.
Map<Vertex<Integer>,Edge<Integer>> vertexToEdge = new HashMap<>();
//stores final result
List<Edge<Integer>> result = new ArrayList<>();
//insert all vertices with infinite value initially.
for(Vertex<Integer> v : graph.getAllVertex()){
minHeap.add(Integer.MAX_VALUE, v);
}
//start from any random vertex
Vertex<Integer> startVertex = graph.getAllVertex().iterator().next();
//for the start vertex decrease the value in heap + map to 0
minHeap.decrease(startVertex, 0);
//iterate till heap + map has elements in it
while(!minHeap.empty()){
//extract min value vertex from heap + map
Vertex<Integer> current = minHeap.extractMin();
//get the corresponding edge for this vertex if present and add it to final result.
//This edge wont be present for first vertex.
Edge<Integer> spanningTreeEdge = vertexToEdge.get(current);
if(spanningTreeEdge != null) {
result.add(spanningTreeEdge);
}
//iterate through all the adjacent vertices
for(Edge<Integer> edge : current.getEdges()){
Vertex<Integer> adjacent = getVertexForEdge(current, edge);
//check if adjacent vertex exist in heap + map and weight attached with this vertex is greater than this edge weight
if(minHeap.containsData(adjacent) && minHeap.getWeight(adjacent) > edge.getWeight()){
//decrease the value of adjacent vertex to this edge weight.
minHeap.decrease(adjacent, edge.getWeight());
//add vertex->edge mapping in the graph.
vertexToEdge.put(adjacent, edge);
}
}
}
return result;
}
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, 3);
graph.addEdge(2, 3, 1);
graph.addEdge(3, 1, 1);
graph.addEdge(1, 4, 1);
graph.addEdge(2, 4, 3);
graph.addEdge(4, 5, 6);
graph.addEdge(5, 6, 2);
graph.addEdge(3, 5, 5);
graph.addEdge(3, 6, 4);
PrimMST prims = new PrimMST();
Collection<Edge<Integer>> edges = prims.primMST(graph);
for(Edge<Integer> edge : edges){
System.out.println(edge);
}
}
}