最小生成树算法——Kruskal算法Java实现

18 篇文章 0 订阅
8 篇文章 0 订阅
闲来无事,写个算法,最小生成树的Kruskal算法,相对比Prim算法实现起来麻烦一点点
package trees;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
/**
 * 最小生成树的Kruskal算法,
 * For a connected weighted graph G, a spanning tree T of G is constructed as follows:
 * For the first edge e1 of T, we select any edge of G of minimum weight and for the second
 * edge e2 of T, we select any remaining edge of G of minimum weight. For the third edge e3
 * of T,we choose any remaining edge of G of minimum weight that dose not produce a cycle with
 * the previousely selected edges. We continue in this manner until a spanning tree is produced.
 * @author xhw
 *
 */
public class KruskalMinimumSpanningTree {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		double graph[][]={{0,1,4,4,5},
						  {1,0,3,7,5},
						  {4,3,0,6,Double.MAX_VALUE},
						  {4,7,6,0,2},
						  {5,5,Double.MAX_VALUE,2,0}};
		double tree[][]=minimumSpanningTree(graph);
		if(tree==null)
		{
			System.out.println("no spanning tree");
			System.exit(0);
		}
		PriorityQueue<Edge> edgeList=generateEdgeList(tree);
		for(Edge e:edgeList)
		{
			System.out.println(e);
		}
		
	}

	/**
	 * 给定一个带权值的邻接矩阵(其中若i=j,权值为0,若i和j不可达权值为Double.max),返回一个最小生成树,
	 * @param graph
	 * @return
	 */
	public static double[][] minimumSpanningTree(double[][] graph) {

		int rlength=graph.length;
		int clength=graph[0].length;
		PriorityQueue<Edge> edgeList;
		edgeList=generateEdgeList(graph);
		double tree[][]=new double[rlength][clength];
		/**
		 * 初始化tree
		 */
		for(int i=0;i<rlength;i++)
		{
			for(int j=0;j<clength;j++)
			{
				if(i==j)
					tree[i][j]=0;
				else
					tree[i][j]=Double.MAX_VALUE;
			}
		}
		
		/**
		 * map用于标识边的某个顶点属于哪个集合,认为顶点刚开始属于不同的集合,当选择一条边时,就合并两个集合,如果选择的边在同一个集合内,就代表有环路出现了
		 */
		Map<Integer,Set<Integer>> map=new HashMap<Integer,Set<Integer>>();
		int edgeCount=0;
		while(edgeCount<rlength-1&&!edgeList.isEmpty())
		{
			Edge e=edgeList.poll();
			
			
			Set<Integer> setU=map.get(e.u);
			Set<Integer> setV=map.get(e.v);
			//System.out.println(e);
			//边的两个顶点都未出现在其他集合中
			if(setU==null&&setV==null)
			{
				Set<Integer> set=new HashSet<Integer>();
				set.add(e.u);
				set.add(e.v);
				map.put(e.u, set);
				map.put(e.v, set);
			}//有一个顶点在其他集合中,一个不在,将不在的那个顶点集合合并进去
			else if(setU==null&&setV!=null)
			{
				map.put(e.u, setV);
				setV.add(e.u);
			}
			else if(setU!=null&&setV==null)
			{
				map.put(e.v, setU);
				setU.add(e.v);
			}//分别在不同的集合中,合并两个集合
			else if(setU!=setV)
			{
				for(int v:setV)
				{
					map.put(v, setU);
					
				}
				
				setU.addAll(setV);
			}//两个顶点在同一个结合中,会出现环路,舍弃
			else
			{
				continue;
			}
			tree[e.u][e.v]=e.weight;
			tree[e.v][e.u]=e.weight;
			edgeCount++;
			
		}
		
		
		if(edgeCount==rlength-1)
			return tree;
		else
			return null;
	}

	/**
	 * 生成边的排序好的队列
	 * @param graph
	 * @return
	 */
	private static PriorityQueue<Edge> generateEdgeList(double[][] graph) {
		PriorityQueue<Edge> edgeList=new PriorityQueue<Edge>();
		int rlength=graph.length;
		int clength=graph[0].length;
		for(int i=0;i<rlength;i++)
		{
			for(int j=i+1;j<clength;j++ )
			{
				if(graph[i][j]>0&graph[i][j]<Double.MAX_VALUE)
				{
					Edge e=new Edge(i,j,graph[i][j]);
					edgeList.add(e);
				}
			}
		}
		return edgeList;
	}

	

}

class Edge implements Comparable<Edge>
{
	int u;
	int v;
	double weight;
	
	
	
	public Edge(int u, int v, double weight) {
		super();
		this.u = u;
		this.v = v;
		this.weight = weight;
	}



	@Override
	public int compareTo(Edge e) {
		if(e.weight==weight)
		return 0;
		else if(weight<e.weight)
			return -1;
		else
			return 1;
			
	}
	
	public String toString()
	{
		return u+"--"+v+":"+weight;
	}
	
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值