java实现最小生成树的prim算法和kruskal算法
在边赋权图中,权值总和最小的生成树称为最小生成树。构造最小生成树有两种算法,分别是prim算法和kruskal算法。在边赋权图中,如下图所示:
在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权值,若要以上图来构建最小生成树。结果应该如下所示:
这样构建的最小生成树的权值总和最小,为17
在构建最小生成树中,一般有两种算法,prim算法和kruskal算法
在prim算法中,通过加入最小邻接边的方法来建立最小生成树算法。首先构造一个零图,在选一个初始顶点加入到新集合中,然后分别在原先的顶点集合中抽取一个顶点,使得构成的边为权值最小,然后将该笔边加入到图中,并将抽出的顶点加入到新集合中,重复这个过程,知道新集合等于原先的集合。
代码一:(java)
1 /** 2 * 最小生成树的prim算法 3 * @author liuy 4 */ 5 public class Prim { 6 7 public static void prim(int num, float[][] weight) { //num为顶点数,weight为权 8 float[] lowcost = new float[num + 1]; //到新集合的最小权 9 10 int[] closest = new int[num + 1]; //代表与s集合相连的最小权边的点 11 12 boolean[] s = new boolean[num + 1]; //s[i] == true代表i点在s集合中 13 14 s[1] = true; //将第一个点放入s集合 15 16 for(int i = 2; i <= num; i++) { //初始化辅助数组 17 lowcost[i] = weight[1][i]; 18 closest[i] = 1; 19 s[i] = false; 20 } 21 22 for(int i = 1; i < num; i++) { 23 float min = Float.MAX_VALUE; 24 int j = 1; 25 for(int k = 2; k <= num; k++) { 26 if((lowcost[k] < min) && (!s[k])) {//根据最小权加入新点 27 min = lowcost[k]; 28 j = k; 29 } 30 } 31 32 System.out.println("加入点" + j + ". " + j + "---" + closest[j]);//新加入点的j和与j相连的点 33 34 s[j] = true;//加入新点j 35 36 for(int k = 2; k <= num; k++) { 37 if((weight[j][k] < lowcost[k]) && !s[k]) {//根据新加入的点j,求得最小权 38 lowcost[k] = weight[j][k]; 39 closest[k] = j; 40 } 41 } 42 } 43 } 44 45 public static void main(String[] args) { 46 // ① 47 // / | / 48 // 6 1 5 49 // / | / 50 // ②-5--③--5--④ 51 // / // / 52 // 3 6 4 2 53 // // // 54 // ⑤--6-⑥ 55 //最小生成树为: 56 // ① 57 // | 58 // 1 59 // | 60 // ②-5--③ ④ 61 // / / / 62 // 3 4 2 63 // / // 64 // ⑤ ⑥ 65 // 66 float m = Float.MAX_VALUE; 67 float[][] weight = {{0, 0, 0, 0, 0, 0, 0}, 68 {0, m, 6, 1, 5, m, m}, 69 {0, 6, m, 5, m, 3, m}, 70 {0, 1, 5, m, 5, 6, 4}, 71 {0, 5, m, 5, m, m, 2}, 72 {0, m, 3, 6, m, m, 6}, 73 {0, m, m, 4, 2, 6, m}};//上图的矩阵 74 prim(weight.length - 1, weight); 75 //加入点3. 3---1 76 //加入点6. 6---3 77 //加入点4. 4---6 78 //加入点2. 2---3 79 //加入点5. 5---2 80 } 81 }
代码二:(java)
1 package 最小生成树; 2 /* 3 * 最小生成树prim算法,加入最小邻接边生成最小生成树。 4 * 首先构造一个零图,选择一个初始点加入到集合中, 5 * 然后分别从原来顶点的集合中抽取一个顶点, 6 * 选择的标准是构造成的树的权值最小, 7 * 循序渐进最终生成一棵最小生成树 8 */ 9 public class prim { 10 11 /* 12 * m:定义为无法到达的距离 13 * weight:邻接矩阵表,weight表示权值 14 * verNum:顶点的个数 15 * lowerW:到新集合的最小权值 16 * edge:存储到新集合的边 17 * checked:判定顶点是否被抽取的集合 18 */ 19 20 static int m=Integer.MAX_VALUE; 21 static int[][] weight={ 22 {0, 0, 0, 0, 0, 0}, 23 {0, m, 6, 9, 5, 13}, 24 {0, 6, m, 6,7,8}, 25 {0, 9,6,m,9,3}, 26 {0, 5,7,9,m,3}, 27 {0,13,8,3,3,m} 28 }; 29 static int verNum=weight.length; 30 static int []lowerW=new int[verNum]; 31 static int []edge=new int[verNum]; 32 static boolean []checked=new boolean[verNum]; 33 34 public void prim(int n,int [][]w){ 35 checked[1]=true; //抽取第一个顶点 36 37 for(int i=1;i<=n;i++){ //初始化顶点集合 38 lowerW[i]=w[1][i]; 39 edge[i]=1; 40 checked[i]=false; 41 } 42 43 for(int i=1;i<=n;i++){ 44 int min=Integer.MAX_VALUE; 45 int j=1; 46 for(int k=2;k<=n;k++){ //判定是否抽取该顶点 47 if(lowerW[k]<min&&(!checked[k])){ 48 min=lowerW[k]; 49 j=k; 50 } 51 } 52 if(i<n) //避免输出第一个顶点到第一个顶点的情况 53 System.out.println(j+"-->"+edge[j]); 54 55 checked[j]=true; //将顶点加入到新集合中 56 57 for(int k=2;k<=n;k++){ //根据新加入的顶点,求得最小的权值 58 if((w[j][k]<lowerW[k])&&(!checked[k])){ 59 lowerW[k]=weight[j][k]; 60 edge[k]=j; 61 } 62 } 63 } 64 } 65 66 public static void main(String[] args) { 67 // TODO Auto-generated method stub 68 prim p=new prim(); 69 p.prim(verNum-1,weight); 70 } 71 }