这个算法,和普利姆算法最后想要的结果是相同的,都是为了获取通过所有点的最短路径。普利姆算法是从点开始查找,自上而下。克鲁斯卡尔算法是从边开始查找。
那么,就让我们就说一说这个算法吧!
先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。
上面内容是百度上给的基本思想,想必大家看完后也有一点小懵。
我将这个算法分为了几个步骤:
第一,添加一个构造器,在构造器中传入点的数组和图的邻接矩阵。
private int edgeNum;
private char[] vertexs;
private int [][] matrix;
private static final int INF = Integer.MAX_VALUE;//表示两个顶点不连通
public Kruska(char[] vertexs, int[][]matrix){
int len = vertexs.length;
this.vertexs=vertexs;
for(int i=0;i<len;i++){
this.vertexs[i]=vertexs[i];
}
this.matrix=matrix;
for(int i=0;i<len;i++){
for(int j=0;j<len;j++){
this.matrix[i][j]=matrix[i][j];
}
}
}
第二,建立一个与边相关的类,里面含有起始点,终止点和点与点之间的距离。
class EData{
char start;
char end;
int weight;
public EData(char start ,char end,int weight){
this.start=start;
this.end=end;
this.weight=weight;
}
@Override
public String toString() {
return "EData<" + start +
"," + end +
">=" + weight;
}
}
第三,通过图的邻接矩阵获取一共有多少条边
int len = vertexs.length;
for(int i=0;i<len;i++){
for(int j=i+1;j<len;j++){
if(matrix[i][j]!=10000){
edgeNum++;
}
}
}
第四,通过遍历邻接矩阵来获得边数组
private EData[] getEdges(){
int index=0;
EData[] edges = new EData[edgeNum];
for(int i=0;i<vertexs.length;i++){
for(int j=i+1;j<vertexs.length;j++){
if(matrix[i][j]!=10000){
edges[index++]=new EData(vertexs[i],vertexs[j],matrix[i][j]);
}
}
}
return edges;
}
第五,对边数组进行排序
private void sort(EData[] edges){
for(int i =0;i<edges.length-1;i++){
for(int j=0;j<edges.length-1;j++){
if(edges[j].weight>edges[j+1].weight){
EData temp = edges[j];
edges[j]=edges[j+1];
edges[j+1]=temp;
}
}
}
}
第六,遍历所有的边,依次找到从小到大的边的距离。(我们在遍历所有边的时候,我们要先判断起点和终点是否在图中,接下来我们 要判断这两个点是否构成回路,如果构成回路则舍弃这条边)
private int getPosition(char ch){
for(int i=0;i<vertexs.length;i++){
if(vertexs[i]==ch){
return i;
}
}
return -1;
}
private int getEnd(int[]ends,int i){
while(ends[i]!=0){
i=ends[i];
}
return i;
}
public void kruskal(){
int index=0;
int[]ends=new int[edgeNum];
EData[]rets= new EData[edgeNum];
EData[]edges=getEdges();
sort(edges);
for(int i=0;i<edgeNum;i++){
int p1=getPosition(edges[i].start);
int p2=getPosition(edges[i].end);
int m=getEnd(ends,p1);
int n=getEnd(ends,p2);
if(m!=n){
ends[m]=n;
rets[index++]=edges[i];
}
}
for(int i=0;i<index;i++){
System.out.println(rets[i]);
}
}