概念
最小生成树的kruskal算法非常简单了,原理和prim算法差不多,然而kruskal并不是从源点开始层次考察的,而是直接用优先队列存储所有边,通过贪心算法的思想,用权重最小的边组成最小生成树。需要注意的是要通过并查集过滤掉组成环的边。
实现
/**
* 最小生成树,克鲁斯卡尔算法
* @author yuli
*
*/
public class KruskalMst {
private LinkedList<Edge> mst;//最小生成树
public KruskalMst(EdgeWeightedUnGraph graph) {
mst = new LinkedList<>();
//使用优先队列来存放边集
PriorityQueue<Edge> queue = new PriorityQueue<>();
//得到边集并加入优先队列
Iterable<Edge> edges = graph.edges();
for (Edge edge : edges) {
queue.offer(edge);
}
//初始化并查集,用来判断加入边后是否会形成环
FastUnionFind uf = new FastUnionFind(graph.getV());
//如果队列为空,或者优先队列小于图的顶点-1(边已经找完了)
while(!queue.isEmpty() && mst.size() < graph.getV()-1){
//出队权重最小的
Edge edge = queue.poll();
//获得两个顶点
int v = edge.getV();
int w = edge.getW();
//判断是否会形成环,如果形成环就跳过
if(uf.isConnected(v, w)){
continue;
}
//连通这两个顶点
uf.union(v, w);
mst.add(edge);
}
}
/**
* 获取最小生成树
* @return
*/
public Iterable<Edge> edges(){
return mst;
}
/**
* 获取最小生成树的权重
* @return
*/
public double weight(){
double weight = 0;
Iterable<Edge> edges = edges();
for (Edge edge : edges) {
weight += edge.getWeight();
}
return weight;
}
}