我自己感觉,克鲁斯卡尔算法比普利姆算法更好理解,它就两个要点,排序和判断是否成环。
排序:我们把两两相邻的边根据边的权值,从小到大依次排序,这个十大排序算法可以自己选一个去实现下,刚好还可以回忆下以前的算法,下面我们使用冒泡来实现边的排序。
是否成环:这个也是这个算法里比较难的一个点了,这里使用了并查集,每次添加一条边时候,我们需要去寻找这两个点是否有相同的父节点,如果有说明成环了,我们就可以选择下一条边了,直到有n-1条边。
如果不了解并查集的,可以看看下面这一篇文章,讲的很通俗易懂。 (https://zhuanlan.zhihu.com/p/93647900)
下面依然是给出关键步骤代码,基本的图数据结构可以自己动手实现哦。
class Edata {
private int start;
private int end;
private int weight;
public Edata(int start, int end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
}
class Graph {
private int verxs;
private char[] data;
private int[][] weigth;
}
private int[] rank;
private Edata[] result;
public void kruskal(Graph graph) {
int index = 0;
Edata[] eDatas = getEDates(graph);
sort(edatas)
for(int i = 0; i < eDatas.length; i++) {
int m = eDatas[i].getStart();
int n = eDatas[i].getEnd();
int a = getRoot(m);
int b = getRoot(n);
if(a != b) {
rank[a] = b;
result[index++] = eDatas[i];
}
}
}
public int getRoot(int n) {
while(rank[n] != n) {
n = rank[n];
}
return n;
}
public void sort(Edata[] eDatas) {
Edata[] edatas = getEDates(graph);
}
public Edata[] getEDates(Graph graph) {
int index = 0;
Edata eDatas = new Edata[graph.getVerxs - 1];
for(int i = 0; i < graph.getVerxs(); i++) {
for(int j = i + 1; j < graph.getVerxs(); j++) {
edatas[index++] = new Edata(graph.getData()[i], graph.getData()[j], graph.getWeight()[i][j]);
}
}
return eDatas;
}
到此克鲁斯卡尔算法算是完了,代码虽然比普利姆的多些,但是结构还是很清楚的,记住两个要点排序,是否成环就OK了。