最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。
Kruskal算法(加边法)
初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里
对给定连通图所有边权值进行排序
对新加入边,进行是否形成回路判断(并查算法)
package com.yue.algorithm.pa01;
import java.util.ArrayList;
public class Kruskal {
class edge {
int startVertex;
int endVertex;
int weight;// 权值
public edge(int startVertex,int endVertex,int weight){
this.startVertex=startVertex;
this.endVertex=endVertex;
this.weight=weight;
}
}
public static void main(String[] args) {
Kruskal y = new Kruskal();
int n=5;//顶点
int p=7;//边
edge[] A=new edge[p];
A[0]=y.new edge(0, 1, 5);
A[1]=y.new edge(1, 2, 5);
A[2]=y.new edge(1, 3, 12);
A[3]=y.new edge(1, 4, 15);
A[4]=y.new edge(2, 3, 17);
A[5]=y.new edge(2, 4, 6);
A[6]=y.new edge(3, 4, 12);
y.getMinSpanTree(n, A);
}
//n==顶点数
public ArrayList<edge> getMinSpanTree(int n, edge[] A) {
ArrayList<edge> rs = new ArrayList<Kruskal.edge>();
int[] parent = new int[n];
for (int i=0;i<n;i++) {
parent[i]=i;//每个顶点的老大都是自己
}
//按边的权值排序
sort(A);
int startVertex,endVertex;
int p1,p2;
for(int i=0;i<A.length;i++) {
startVertex = A[i].startVertex;
endVertex = A[i].endVertex;
p1 = find(parent, startVertex);
p2 = find(parent, endVertex);
if(p1!=p2) {
rs.add(A[i]);
union(parent, startVertex, endVertex);
}
if(rs.size()==n-1) {
break;
}
}
for (edge ed : rs) {
System.out.println(ed.startVertex+"---"+ed.endVertex+"---"+ed.weight);
}
return rs;
}
//并查集
public void union(int[] parent, int index1, int index2) {
parent[find(parent, index1)] = find(parent, index2);
}
public int find(int[] parent, int index) {
while (parent[index] != index) {
parent[index] = parent[parent[index]];
index = parent[index];
}
return index;
}
// 2-路归并排序
public void sort(edge[] A) {
if (A.length <= 1) return;
int mid = A.length/2;
edge[] left = getHalfEdge(A, 0,mid-1);
edge[] right = getHalfEdge(A, mid,A.length-1);
sort(left);
sort(right);
merge(A,left,right);
}
private void merge(edge[] A,edge[] left, edge[] right) {
int l=0,r=0,index=0;
while(l<left.length && r<right.length) {
if(left[l].weight>right[r].weight) {
A[index++]=right[r++];
}else {
A[index++]=left[l++];
}
}
while(l<left.length) {
A[index++]=left[l++];
}
while(r<right.length) {
A[index++]=right[r++];
}
}
private edge[] getHalfEdge(edge[] A, int s,int e) {
edge[] rs = new edge[e-s+1];
for(int i=s;i<=e;i++) {
rs[i-s]=A[i];
}
return rs;
}
}