java编写Kruskal算法实现最小生成树

Kruskal算法

算法思想很简单就是一个图中最短(权值最小)的那条边就是最小生成树中的边,但是若加上这条边后最小生成树中形成了“环”,则排除这条边继续找出剩下边中的最短边加入最小生成树。而判断是否形成了“环”则是通过并查集的isConnected方法来判断两点(这俩点已在最小生成树中)是否已相连,若已相连我再把这条边加入最小生成树中不就出现“环”了么!(关于并查集的isConnecte方法介绍请看我的另一篇博客)

实现代码:类KruskalMST

public class KruskalMST {
	
	private ArrayList<Edge> mst=new ArrayList<Edge>();  //存储最小生成树的Edge
	private int mstWeight;    //最小的权值和
	
	public KruskalMST(SparseGraph sg) {
		MinHeap mh=new MinHeap(sg.E());
		for(int i=0;i<sg.V();i++){
			ArrayList<Edge> arr=sg.getGraph(i);
			Iterator<Edge> ite=arr.iterator();
			while(ite.hasNext()){
				Edge ed=ite.next();
				if(ed.v()<ed.w()){   //防止插入重复边
					mh.insert(ed);
				}				
			}
		}
		
		UnionFind uf=new UnionFind(sg.V());     //通过并查集来检测是否出现"环"
		while(!mh.isEmpty()&&mst.size()<(sg.V()-1)){
			Edge e=mh.extractMin();
			if(uf.isConnected(e.v(), e.w())){
				continue;
			}
			mst.add(e);
			uf.unionElements(e.v(), e.w());  //将e.v()和e.w()合并
		}
		mstWeight=mst.get(0).wt();
		for(int i=1;i<mst.size();i++){
			mstWeight+=mst.get(i).wt();
		}
	}

	public ArrayList<Edge> mstEdges(){
		return mst;
	}
	
	public int result(){
		return mstWeight;
	}

}

比较Prim、LazyPrim、Kruskal算法的效率:

比较代码:

int N=30;  //顶点
		int M=200;   //边
		SparseGraph sg=new SparseGraph(N,false);
		for(int i=0;i<M;i++){
			sg.addEdge(new Random().nextInt(N), new Random().nextInt(N),new Random().nextInt(100)+1);//权值[1,101)
		}
		System.out.println("PrimMST耗时:");
		long startTime=System.nanoTime();   //获取开始时间
		PrimMST la=new PrimMST(sg);
		long endTime=System.nanoTime(); //获取结束时间  
		System.out.println("程序运行时间: "+(endTime-startTime)+" 纳秒"); 
		
		System.out.println("LazyPrimMST耗时:");
		long s_startTime=System.nanoTime();   //获取开始时间
		LazyPrimMST lpm=new LazyPrimMST(sg);
		long s_endTime=System.nanoTime(); //获取结束时间  
		System.out.println("程序运行时间: "+(s_endTime-s_startTime)+" 纳秒"); 

		
		System.out.println("KruskalMST耗时:");
		long t_startTime=System.nanoTime();   //获取开始时间
		KruskalMST km=new KruskalMST(sg);
		long t_endTime=System.nanoTime(); //获取结束时间  
		System.out.println("程序运行时间: "+(t_endTime-t_startTime)+" 纳秒"); 

比较结果



Kruskal算法实现起来比较简单,不过速度上大致还是比Prim算法慢一点的



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
克鲁斯卡尔算法是一种求解最小生成树的经典算法,其基本思想是贪心算法。以下是使用Java实现克鲁斯卡尔算法构造最小生成树的代码: ```java import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; class Graph { private int[] parent; private int[] rank; public Graph(int n) { parent = new int[n]; rank = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; rank[i] = 0; } } private int find(int x) { if (parent[x] != x) { parent[x] = find(parent[x]); } return parent[x]; } private void union(int x, int y) { int xRoot = find(x); int yRoot = find(y); if (rank[xRoot] < rank[yRoot]) { parent[xRoot] = yRoot; } else if (rank[xRoot] > rank[yRoot]) { parent[yRoot] = xRoot; } else { parent[xRoot] = yRoot; rank[yRoot]++; } } public List<Edge> kruskalMST(List<Edge> edges) { List<Edge> result = new ArrayList<>(); Collections.sort(edges, Comparator.comparingInt(e -> e.weight)); for (Edge edge : edges) { int u = edge.u; int v = edge.v; int w = edge.weight; if (find(u) != find(v)) { union(u, v); result.add(edge); } } return result; } } class Edge { int u; int v; int weight; public Edge(int u, int v, int weight) { this.u = u; this.v = v; this.weight = weight; } } public class KruskalMST { public static void main(String[] args) { int n = 5; List<Edge> edges = new ArrayList<>(); edges.add(new Edge(0, 1, 2)); edges.add(new Edge(0, 3, 6)); edges.add(new Edge(1, 2, 3)); edges.add(new Edge(1, 3, 8)); edges.add(new Edge(1, 4, 5)); edges.add(new Edge(2, 4, 7)); edges.add(new Edge(3, 4, 9)); Graph graph = new Graph(n); List<Edge> result = graph.kruskalMST(edges); for (Edge edge : result) { System.out.println(edge.u + " - " + edge.v + ": " + edge.weight); } } } ``` 在上面的代码中,我们首先定义了一个Graph类,其中包含了find和union两个函数,分别用于查找节点的根节点和合并两个不同的集合。然后,我们定义了一个Edge类,用于表示图中的边。最后,在main函数中,我们定义了一个包含边的列表,然后使用Graph类的kruskalMST函数求解最小生成树,并打印结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值