【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
package org.loda.graph;
import org.loda.structure.MinQ;
import org.loda.structure.Queue;
import org.loda.util.In;
/**
*
* @ClassName: KruskalMST
* @Description:Kruskal最小生成树算法
* @author minjun
* @date 2015年5月25日 下午10:50:01
*
*/
public class KruskalMST {
private Queue<Edge> mst;
private double weight;
public KruskalMST(WeightGraph g){
int v=g.v();
mst=new Queue<Edge>();
MinQ<Edge> q=new MinQ<Edge>();
UF uf=new UF(v);
//将所有边添加到优先队列中
for(Edge edge:g.edges()){
q.offer(edge);
}
while(!q.isEmpty()){
Edge edge=q.poll();
int a=edge.oneSide();
int b=edge.otherSide(a);
//如果已经连通,说明这条边无法继续加入,否则会形成环路
if(uf.connected(a, b)) continue;
//将两个连通分量连通
uf.union(a, b);
mst.enqueue(edge);
weight+=edge.weight();
}
}
/**
*
* @Title: edges
* @Description: 最小生成树的所有边
* @param @return 设定文件
* @return Iterable<Edge> 返回类型
* @throws
*/
public Iterable<Edge> edges(){
return mst;
}
/**
*
* @Title: weight
* @Description: 最小生成树的权重
* @param @return 设定文件
* @return double 返回类型
* @throws
*/
public double weight(){
return weight;
}
public static void main(String[] args) {
In in = new In("F:\\算法\\attach\\tinyEWG.txt");
WeightGraph g = new WeightGraph(in);
KruskalMST m = new KruskalMST(g);
for (Edge e : m.edges()) {
System.out.println("边:"+e);
}
System.out.println(m.weight());
}
}
所依赖的数据结构和前一篇的Prim算法相同,都是带权重边的无向图,和一条权重边,不过由于Kruskal算法的核心思想是不断找到最小的边,并查看他们连通与否,如果不连通,则合并他们成同一个连通分量,并将这条边加入到最小生成树。需要检测无向图的连通性,则需要利用到另外一个算法union-find并查集,下面给出并查集的简单实现
package org.loda.graph;
/**
*
* @ClassName: UF
* @Description:并查集
* @author minjun
* @date 2015年5月25日 下午11:41:16
*
*/
public class UF {
//每个元素的标识
private int[] id;
//连通分量数量
private int count;
public UF(int n){
id=new int[n];
//初始化为n个不相连的点(连通分量)的值
count=n;
for(int i=0;i<n;i++){
id[i]=i;
}
}
/**
*
* @Title: connected
* @Description: 判断两点是否连通
* @param @param a
* @param @param b
* @param @return 设定文件
* @return boolean 返回类型
* @throws
*/
public boolean connected(int a,int b){
return find(a)==find(b);
}
/**
*
* @Title: union
* @Description: 合并两个连通分量
* @param @param a
* @param @param b 设定文件
* @return void 返回类型
* @throws
*/
public void union(int a,int b){
int A=find(a);
int B=find(b);
//如果相等,表示已经合并成一个连通分量了
if(A==B) return;
//合并所有属于b的连通分量为a
for(int i=0;i<id.length;i++){
if(id[i]==B)
id[i]=A;
}
count--;
}
/**
*
* @Title: find
* @Description: 查找连通分量的值
* @param @param a
* @param @return 设定文件
* @return int 返回类型
* @throws
*/
public int find(int a){
return id[a];
}
public int count(){
return count;
}
public static void main(String[] args) {
UF qf=new UF(10);
qf.union(4, 3);
qf.union(3, 8);
qf.union(6, 5);
qf.union(9, 4);
qf.union(2, 1);
qf.union(5, 0);
qf.union(7, 2);
qf.union(6, 1);
qf.union(1, 0);
qf.union(6, 7);
System.out.println("connected :"+qf.count()+","+qf.connected(5, 9));
}
}
8
16
4 5 0.35
4 7 0.37
5 7 0.28
0 7 0.16
1 5 0.32
0 4 0.38
2 3 0.17
1 7 0.19
0 2 0.26
1 2 0.36
1 3 0.29
2 7 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93
输出结果为 :
边:0-7 0.16
边:2-3 0.17
边:1-7 0.19
边:0-2 0.26
边:5-7 0.28
边:4-5 0.35
边:6-2 0.4
1.81
来源:oschina
链接:https://my.oschina.net/u/1378920/blog/419904