Kruskal算法简单易懂的描述:
假设有如下图:
将上图按边的权值从小到大排序:
按边的权值从小到大
取边加入生成树,注意:最小生成树是不能有环的,所以每取一条边都要检查所取边的两个端点是否在之前取边时都取过,如果都取过则不能取该条边(需要继续往下检查看接下来的边能否取),如果只有一个端点曾经取过,那么这条边依然是可以加入生成树的。
当取到的边总数等于顶点总数减1
时,最小生成树就生成了。如图:
代码实现:
边集:
public class Edge<T>implements Comparable<Edge> {
private T start;
private T end;
private int distance;
public Edge(T start, T end, int distance) {
this.start = start;
this.end = end;
this.distance = distance;
}
public T getStart() {
return start;
}
public void setStart(T start) {
this.start = start;
}
public T getEnd() {
return end;
}
public void setEnd(T end) {
this.end = end;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
@Override
public String toString() {
return start + "->" + end + ":" + distance;
}
@Override
public int compareTo(Edge obj) {
int targetDis = obj.getDistance();
return distance > targetDis ? 1 : (distance == targetDis ? 0 : -1);
}
}
并查集:
import java.util.HashSet;
import java.util.Set;
public class UnionFind {
public static class UFNode {
UFNode parent;
}
public static UFNode find(UFNode x) {
UFNode p = x;
Set<UFNode> path = new HashSet<>();
while (p.parent != null) {
path.add(p);
p = p.parent;
}
for (UFNode ppp : path) {
ppp.parent = p;
}
return p;
}
public static void union(UFNode x, UFNode y) {
find(y).parent = find(x);
}
}
Kruskal算法:
import java.util.*;
public class Kruskal {
private final List<Edge> edgeList;
private Set<Edge> T = new HashSet<>();
public Set<Edge> getT() {
buildMST();
return T;
}
private final int n;
private Map pntAndNode = new HashMap();
public Kruskal(List<Edge> edgeList, int n) {
this.edgeList = edgeList;
this.n = n;
for (Edge edge : edgeList) {
pntAndNode.put(edge.getStart(), new UnionFind.UFNode());
pntAndNode.put(edge.getEnd(), new UnionFind.UFNode());
}
}
public static void main(String[] args) {
List<Edge> edgeList = build();
Kruskal obj = new Kruskal(edgeList, 5);
for (Edge e : obj.getT()) {
System.out.println(e);
}
}
private static List<Edge> build() {
List<Edge> l = new ArrayList<>();
l.add(new Edge(("C"), "D", 1));
l.add(new Edge(("C"), "A", 1));
l.add(new Edge(("C"), "E", 2));
l.add(new Edge(("A"), "B", 3));
l.add(new Edge(("D"), "E", 3));
l.add(new Edge(("B"), "C", 5));
l.add(new Edge(("B"), "E", 6));
l.add(new Edge(("B"), "D", 7));
l.add(new Edge(("A"), "D", 2));
l.add(new Edge(("A"), "E", 9));
return l;
}
private void buildMST() {
Collections.sort(edgeList);
for (Edge e : edgeList) {
if (!ok(e)) {
continue;
}
T.add(e);
if (T.size() == n - 1) {
return;
}
}
}
private boolean ok(Edge e) {
UnionFind.UFNode x = (UnionFind.UFNode) pntAndNode.get(e.getStart());
UnionFind.UFNode y = (UnionFind.UFNode) pntAndNode.get(e.getEnd());
if (UnionFind.find(x) != UnionFind.find(y)) {
UnionFind.union(x, y);
return true;
}
return false;
}
}
运行结果截图