最小生成树的Prim算法和Kruskal算法java代码实现

MiniSpanTree中两个静态函数实现了最小生成树的Prim算法和Kruskal算法:

原文链接:http://blog.csdn.net/witsmakemen/article/details/8889256

[java]  view plain  copy
  1. package datastucture;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Arrays;  
  5. import java.util.HashSet;  
  6. import java.util.Set;  
  7.   
  8. /** 
  9.  * 图的最小树生成算法 
  10.  * @author win7 
  11.  * 
  12.  */  
  13. public class MiniSpanTree {  
  14.     /** 
  15.      * 求图最小生成树的PRIM算法 
  16.      * 基本思想:假设N=(V,{E})是联通网,TE是N上的最想生成树中的变得集合。算法从U={u0}(u0属于V), 
  17.      * TE={}开始,重复执行下述操作:在所有的u属于U,v属于V-U的边(u,v)属于E中找到一条代价最小 
  18.      * 的边(u0,v0)并入集合TE,同事v0并入U,直至U=V为止。此时TE中必有n-1条边,则T=(V,{TE}) 
  19.      * 为N的最小生成树。 
  20.      * @param  graph  图 
  21.      * @param start 开始节点 
  22.      * @param n     图中节点数 
  23.      */  
  24.     public static void PRIM(int [][] graph,int start,int n){  
  25.         int [][] mins=new int [n][2];//用于保存集合U到V-U之间的最小边和它的值,mins[i][0]值表示到该节点i边的起始节点  
  26.                                      //值为-1表示没有到它的起始点,mins[i][1]值表示到该边的最小值,  
  27.                                      //mins[i][1]=0表示该节点已将在集合U中  
  28.         for(int i=0;i<n;i++){//初始化mins  
  29.           
  30.             if(i==start){  
  31.                 mins[i][0]=-1;  
  32.                 mins[i][1]=0;  
  33.             }else if( graph[start][i]!=-1){//说明存在(start,i)的边  
  34.                 mins[i][0]=start;  
  35.                 mins[i][1]= graph[start][i];  
  36.             }else{  
  37.                 mins[i][0]=-1;  
  38.                 mins[i][1]=Integer.MAX_VALUE;  
  39.             }  
  40. //          System.out.println("mins["+i+"][0]="+mins[i][0]+"||mins["+i+"][1]="+mins[i][1]);  
  41.         }  
  42.         for(int i=0;i<n-1;i++){  
  43.             int minV=-1,minW=Integer.MAX_VALUE;  
  44.             for(int j=0;j<n;j++){//找到mins中最小值,使用O(n^2)时间  
  45.                   
  46.                 if(mins[j][1]!=0&&minW>mins[j][1]){  
  47.                     minW=mins[j][1];  
  48.                     minV=j;  
  49.                 }  
  50.             }  
  51. //          System.out.println("minV="+minV);  
  52.             mins[minV][1]=0;  
  53.             System.out.println("最小生成树的第"+i+"条最小边=<"+(mins[minV][0]+1)+","+(minV+1)+">,权重="+minW);  
  54.             for(int j=0;j<n;j++){//更新mins数组  
  55.                 if(mins[j][1]!=0){  
  56. //                  System.out.println("MINV="+minV+"||tree[minV][j]="+tree[minV][j]);  
  57.                     if( graph[minV][j]!=-1&& graph[minV][j]<mins[j][1]){  
  58.                         mins[j][0]=minV;  
  59.                         mins[j][1]= graph[minV][j];  
  60.                     }  
  61.                 }  
  62.             }  
  63.         }  
  64.     }  
  65.   
  66.     /** 
  67.      * 求最小树的Kruskal算法 
  68.      * 算法思想:克鲁斯卡尔算法从另一个途径求网中的最小生成树。假设联通网N=(V,{E}),则令 
  69.      * 最小生成树的厨师状态为只有n个顶点而无边的非连通图T=(V,{}),途中每个顶点自称一个连通分量。 
  70.      * 在E中选择代价最小的边,若该边衣服的顶点落在T中不同的连通分量上,则将此边加入到T中,否则舍去此边 
  71.      * 而选择下一条最小的边。以此类推,直至T中所有的顶点都在同一连通分量上为止。 
  72.      * @param V 图中的节点集合 
  73.      * @param E 图中边的集合 
  74.      */  
  75.     public static void KRUSKAL(int [] V,Edge [] E){  
  76.         Arrays.sort(E);//将边按照权重w升序排序  
  77.         ArrayList<HashSet> sets=new ArrayList<HashSet>();  
  78.         for(int i=0;i<V.length;i++){  
  79.             HashSet set=new HashSet();  
  80.             set.add(V[i]);  
  81.             sets.add(set);            
  82.         }  
  83.           
  84.         System.out.println("++++++++++++++++++++++size="+sets.size());  
  85.         for(int i=0;i<E.length;i++){  
  86.             int start=E[i].i,end=E[i].j;  
  87.             int counti=-1,countj=-2;  
  88.             for(int j=0;j<sets.size();j++){  
  89.                 HashSet set=sets.get(j);  
  90.                 if(set.contains(start)){  
  91.                     counti=j;  
  92.                 }  
  93.                       
  94.                 if(set.contains(end)){  
  95.                     countj=j;  
  96.                 }  
  97.             }  
  98.             if(counti<0||countj<0) System.err.println("没有在子树中找到节点,错误");  
  99.               
  100.             if(counti!=countj){  
  101.                 System.out.println("输出start="+start+"||end="+end+"||w="+E[i].w);  
  102.                 HashSet setj=sets.get(countj);  
  103.                 sets.remove(countj);  
  104.                 HashSet seti=sets.get(counti);  
  105.                 sets.remove(counti);  
  106.                 seti.addAll(setj);  
  107.                 sets.add(seti);  
  108.             }else{  
  109.                 System.out.println("他们在一棵子树中,不能输出start="+start+"||end="+end+"||w="+E[i].w);  
  110.   
  111.             }  
  112.         }  
  113.           
  114.           
  115.     }  
  116.       
  117.     public static void main(String [] args){  
  118.         int [][] tree={  
  119.                 {-1,6,1,5,-1,-1},  
  120.                 {6,-1,5,-1,3,-1},  
  121.                 {1,5,-1,5,6,4},  
  122.                 {5,-1,5,-1,-1,2},  
  123.                 {-1,3,6,-1,-1,6},  
  124.                 {-1,-1,4,2,6,-1}              
  125.         };  
  126.         MiniSpanTree.PRIM(tree, 06);  
  127.         System.out.println("+++++++++++++++++++++++++++++++++");  
  128.   
  129.         int [] V={1,2,3,4,5,6};  
  130.         Edge [] E=new Edge[10];  
  131.         E[0]=new Edge(1,2,6);  
  132.         E[1]=new Edge(1,3,1);  
  133.         E[2]=new Edge(1,4,5);  
  134.         E[3]=new Edge(2,3,5);  
  135.         E[4]=new Edge(2,5,3);  
  136.         E[5]=new Edge(3,4,5);  
  137.         E[6]=new Edge(3,5,6);  
  138.         E[7]=new Edge(3,6,4);  
  139.         E[8]=new Edge(4,6,2);  
  140.         E[9]=new Edge(5,6,6);  
  141.         MiniSpanTree.KRUSKAL(V, E);  
  142.     }  
  143.   
  144. }  
[java]  view plain  copy
  1.   


上面代码中还需要一个边的辅助类Edge,代码如下:


[java]  view plain  copy
  1. package datastucture;  
  2.   
  3. public class Edge implements Comparable{  
  4.     public int i,j,w;  
  5.     public Edge(int i,int j,int w){  
  6.         this.i=i;  
  7.         this.j=j;  
  8.         this.w=w;  
  9.     }  
  10.       
  11.   
  12.     @Override  
  13.     public int compareTo(Object o) {  
  14.         Edge to=(Edge)o;  
  15.         if(this.w>to.w) return 1;  
  16.         else if(this.w==to.w) return 0;  
  17.         else return -1;  
  18.           
  19.     }  
  20.     @Override  
  21.     public String toString() {  
  22.         return "start="+i+"||end="+j+"||w="+w;  
  23.     }  
  24. }  
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值