最小生成树其实就是最小权重生成树的简称。
在一个图里面有很多条边,每条边都有权重。使得每个节点都可以相互联通且整体的权重最小的边的集合就是最小生成树。
思路:
假设每个节点都有一个集合,这个集合就是这个节点联通的节点。在开始没有边的时候,这个集合内只有自己。
把边按照权重从小到大的顺序进行排列。
每次拿出一条边(权重最小的)加入到图中。
如果边的 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;
}