1.直接附代码
/**
* 克鲁斯卡尔(Kruskal)算法-最小生成树
*/
public void kruskal() {
int index = 0; //结果数组的索引
int[] vends = new int[mVexs.length]; //用于保存已有最小生成树中每个顶点在该最小树中的终点(表示第i个顶点对应的终点是j,则这么存vends[i]=j)
Edge[] rets = new Edge[mEdgeNum]; //结果数组,用于存kruskal最小生成树的边
Edge[] edges; //图对应的所有的边
//获取图中所有的边
edges = getEdges();
//将图中所有的边按照由小到大的顺序排序
sortEdges(edges, mEdgeNum);
for (int i = 0; i < mEdgeNum; i++) {
int p1 = getPostion(edges[i].from);
int p2 = getPostion(edges[i].to); //获取第i条边的起点的位置和终点的位置
int m=getEnd(vends,p1);
int n=getEnd(vends,p2);
//如果两个顶点都最终指向同一个顶点,则会造成回路,此时判断是否造成回路,如果不造成回路,则将边放于kruskal最小生成树的边数组中
if(m!=n){
vends[m]=n;
rets[index++]=edges[i];
}
}
for(int i=0;i<vends.length;i++){
System.out.println(vends[i]);
}
int length=0;
for(int i=0;i<index;i++){
length+=rets[i].weight;
}
System.out.println("Kruskal:"+length);
for(int i=0;i<index;i++){
System.out.println(rets[i].from+"->"+rets[i].to);
}
}
/**
* 获取图中的边
*
* @return
*/
private Edge[] getEdges() {
int index = 0;
Edge[] edges;
edges = new Edge[mEdgeNum];
for (int i = 0; i < mVexs.length; i++) {
ENode node = mVexs[i].firstEdge;
while (node != null) {
//如果是无向图的话,同一个边,方向不同,将会存取一条
if (node.ivex > i) {
edges[index++] = new Edge(mVexs[i].data, mVexs[node.ivex].data, node.weight);
}
node = node.nextEdge;
}
}
return edges;
}
/**
* 对边进行排序(由小到大)
*
* @param edges
* @param mEdgeNum
*/
public void sortEdges(Edge[] edges, int mEdgeNum) {
for (int i = 0; i < mEdgeNum; i++) {
for (int j = i + 1; j < mEdgeNum; j++) {
if (edges[i].weight > edges[j].weight) {
Edge temp = edges[i];
edges[i] = edges[j];
edges[j] = temp;
}
}
}
}
//获取i的终点,最终指向终点,加入C->D,D->E,已知D的终点是E,vends[4]=5;C->D,vends[2]=4;此时getEnd(i=2)求得的结果便是5,相当于通过D间接指向E
private int getEnd(int[] vends, int i) {
while (vends[i] != 0) {
i = vends[i];
}
return i;
}
2.原理:
3.算法分析: