Kruskal算法计算最小生成树(java)

最小生成树定义:
每一个无向图可拆分成多个子图,在这些子图中,如果图的各个顶点没有形成回路,则是图的一颗生成树。
最小生成树的意识是树的相邻节点距离之和最小。

应用场景:
张三被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。
张三已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场,问要如何实现。

算法实现:
有关最小生成树的问题常见的算法有两种,分别是Kruskal(克鲁斯卡尔)算法和Prim(普里姆)算法,本文讲解Kruskal算法的实现

Kruskal算法的计算流程大致如下:
1.将无向图的边按距离长短递增式排序,放到集合中
2.遍历该集合,找出最短的边,加入到结果生成树的集合中
3.如果结果生成树出现回路,则放弃这条边
4.重新执行步骤2,直至所有顶点被遍历
可以看出在每次遍历过程中采用了贪心算法

算法实例图:


代码实现:
Edge类用与封装无向图中每条边的信息
public class Edge implements Comparable{
	private String start;
	private String end;
	private int distance;
	public Edge(String start,String end,int distance){
		this.start=start;
		this.end=end;
		this.distance=distance;
	}
	public String getStart() {
		return start;
	}
	public void setStart(String start) {
		this.start = start;
	}
	public String getEnd() {
		return end;
	}
	public void setEnd(String end) {
		this.end = end;
	}
	public int getDistance() {
		return distance;
	}
	public void setDistance(int distance) {
		this.distance = distance;
	}
	@Override
	public String toString() {
		return start + "->" + end;
	}
	@Override
	public int compareTo(Edge obj) {
		int targetDis=obj.getDistance();
		return distance>targetDis?1:(distance==targetDis?0:-1);
	}
}
MapBuilder类用于构建数据源(数据源结构如上图所示):
public class MapBuilder {
	public TreeSet build(){
		TreeSet edges=new TreeSet();
		edges.add(new Edge("A","B",1));
		edges.add(new Edge("A","C",4));
		edges.add(new Edge("A","F",6));
		edges.add(new Edge("B","D",8));
		edges.add(new Edge("B","E",3));
		edges.add(new Edge("C","F",5));
		edges.add(new Edge("C","E",9));
		edges.add(new Edge("D","E",7));
		edges.add(new Edge("D","F",10));
		edges.add(new Edge("E","F",2));
		return edges;
	}
	public int getPointNum(){
		return 6;
	}
}
Kruskal类用于计算最小生成树
public class Kruskal {
	private Set points=new HashSet();
	private List treeEdges=new ArrayList();
	public void buildTree(){
		MapBuilder builder=new MapBuilder();
		TreeSet edges=builder.build();
		int pointNum=builder.getPointNum();
		for(Edge edge:edges){
			if(isCircle(edge)){
				continue;
			}else{//没有出现回路,将这条边加入treeEdges集合
				treeEdges.add(edge);
				//如果边数等于定点数-1,则遍历结束
				if(treeEdges.size()==pointNum-1){
					return;
				}
			}
		}
	}
	public void printTreeInfo(){
		int totalDistance=0;
		for(Edge edge:treeEdges){
			totalDistance+=edge.getDistance();
			System.out.println(edge.toString());
		}
		System.out.println("总路径长度:"+totalDistance);
	}
	private boolean isCircle(Edge edge){
		int size=points.size();
		if(!points.contains(edge.getStart())){
			size++;
		}
		if(!points.contains(edge.getEnd())){
			size++;
		}
		if(size==treeEdges.size()+1){
			return true;
		}else{
			points.add(edge.getStart());
			points.add(edge.getEnd());
			return false;
		}
	}
}
Main类用于测试Kruskal算法
public class Main {
	public static void main(String[] args) {
		Kruskal test=new Kruskal();
		test.buildTree();
		test.printTreeInfo();
	}
}
打印输出:
A->B
E->F
B->E
A->C
D->E
总路径长度:17

你可能感兴趣的:(算法)