图的最小生成树Kruskal算法

这篇博客介绍了如何运用Kruskal算法找到图的最小生成树。首先,通过创建一个MySets类来管理节点的集合,并实现判断集合是否相同和合并集合的方法。接着,利用优先级队列按权重排序边,依次选择权值最小的边,如果连接的节点不在同一集合中,则将其加入结果集并合并集合。最后,返回包含最小权值边的结果集。
摘要由CSDN通过智能技术生成

最小生成树其实就是最小权重生成树的简称。

在一个图里面有很多条边,每条边都有权重。使得每个节点都可以相互联通且整体的权重最小的边的集合就是最小生成树。

思路:

假设每个节点都有一个集合,这个集合就是这个节点联通的节点。在开始没有边的时候,这个集合内只有自己。

把边按照权重从小到大的顺序进行排列。

每次拿出一条边(权重最小的)加入到图中。

如果边的 from节点的联通集合和 to节点的联通集合不相等的话,那么这条边就是可以用的。

然后把to节点联通集合内的所有节点加入到from节点中,然后让to 的联通集合也等于from的联通集合。

	public static class MySets{
		public HashMap<Node, List<Node>> setMap;
		//setMap中包含了每个点对应的集合
		public MySets(List<Node> nodes) {
			
			for(Node node:nodes) {
				List<Node> set = new ArrayList<Node>();
				//开始的时候每个点对应的集合只有自己。
				set.add(node);
				setMap.put(node, set);
			}
			
		}
		
		//判断两个集合是否为空
		public boolean isSameSet(Node from,Node to) {
		
			return setMap.get(from) == setMap.get(to);
		}
		
		//合并两个集合
		public void union(Node from,Node to) {
			List<Node> fromSet = setMap.get(from);
			List<Node> toSet = setMap.get(to);
			for(Node node:toSet) {
				//将to集合中的元素全部加到from中
				fromSet.add(node);
			}
			//再将from的集合复制到to的集合中去。
			setMap.put(to, fromSet);
		}
	}
	
	
	//比较器
	public static class EdgeComparator implements Comparator<Edge>{

		@Override
		public int compare(Edge o1, Edge o2) {
			// TODO Auto-generated method stub
			return o1.weight-o2.weight;
		}
		
	}
	
	
	
	public static Set<Edge> kruskaMST(Graph graph){
		//优先级队列、小根堆,将边按照权重从小到大排列。
		PriorityQueue<Edge> p = new PriorityQueue<Edge>(new EdgeComparator());
		for(Edge edge:graph.edges) {
			p.add(edge);
		}
		MySets sets = new MySets((List<Node>) graph.nodes.values());
		Set<Edge> resultSet = new HashSet<Edge>();
		while(!p.isEmpty()) {
			Edge e = p.poll();
			//如果两个集合不相等,那这条边加进去就不会形成环。
			if(!sets.isSameSet(e.from, e.to)) {
				resultSet.add(e);
				sets.union(e.from,e.to );
			}
			
		}
		return resultSet;
		
		
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值