最小生成树--普利姆(Prim)算法

转自 http://blog.csdn.net/pigli/article/details/5776587

最小生成树

1. 为什么要构造最小生成树?什么是最小生成树?
假设要在n个城市之间建立通信联络网,则连通n个城市只需要n-1条线路。这时,自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信网。
在每两个城市之间都可以设置一条线路,相应地都要付出一定的经济代价。N个城市之间,最多可以设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少呢?
在n个城市之间架设n-1条线路,使得这n个城市是连通的,这就是一个构造生成树的过程.在这n(n-1)/2中可能的方案中,选取总的耗费最小那一颗生成树,这就是最小生成树。
2.  如何构造最小生成树?
构造最小生成树的算法有普利姆(Prim)算法和克鲁斯卡(Kruskal)算法。这两个算法都是利用了最小生成树的性质:假设N=(V,{E})是一个连通网,U是顶点集V的一个非空子集。若(u,v)是一条具有最小权值的边,其中u属于U,v属于V-U,则必存在一颗包含边(u,v)的最小生成树。
本文将实现普利姆(Prim)算法。那么首先来看看Prim算法实现的基本原理:假设N=(V,{E})是一个连通网,TE是N上最小生成树中边的集合。算法从U={u0}(u0 属于V),TE={}开始,重复执行下述操作:在所有的u属于U,v属于V-U中的边(u,v) E中找一条代价最小的边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止。此时TE中必有n-1条边,则N=(V,{TE})为N的最小生成树。
思路决定出路。上面啰嗦这么多,只是为了从本质上认识最小生成树,以及最小生成树构造的原理。思路理清楚了,实现只不过是个过程而已,不会有迈步过去的砍。下面我们再更详细地描述下Prim算法。功夫不会负有心人的,磨刀也不会无砍柴工,相信我!思路理清楚了,程序写起来很快滴!^0^
为了实现这个算法需附设一个辅助数组closedge,以记录从U到V-U具有最小代价的边。对每个顶点vi V-U,在辅助数组中存在一个相应分量closedge[i-1],它包括两个域:vex和lowcost。closedge[i-1].lowcost=Min{cost(u,vi)|u U}。vex域存储该边依附在U中的顶点。


具体算法描述:
1. 初始化closedge数组,用起始顶点到其它各结点权值初始化该数组。
2. 找出closegde数组中最小的权值的那个数组元素closedge[k]并将k并入到U中。这个并入的过程用将closegde[k].lowcost修改为0来标记。(V-U中各顶点到U中各顶点的权值最小的那个顶点。)
3. 将结点k到其它结点j(1<=j<=vetexnum)的权值arc[k][j]与数组closedge[j]. lowcost进行比较。若arc[k][j]<closedge[j]. lowcost,则closedge[j].lowcost = arc[k][j]。这样closegde数组中存储的就是V-U中各顶点到U中各顶点的最小值。(U中增加元素了,修改closedge)。
4. 若U==V则退出,最小生成树生成。否则,返回步骤2。

记住:closegde[j].lowcost中存储的是V-U中结点j到U中各结点的最小权值。

下面是算法实现:(思路清白了,程序实现20分钟就搞定^0^)

 

 

[java] view plaincopy
 
  1. package graph;  
  2. public class MiniSpanTree_PRIM   
  3. {  
  4.     private Closedge[] closedge;   
  5.     class Closedge{  
  6.         String vetex;  
  7.         int lowcost;  
  8.           
  9.         public Closedge(String vetex,int lowcost)  
  10.         {  
  11.             this.vetex = vetex;  
  12.             this.lowcost = lowcost;  
  13.         }  
  14.     }  
  15.       
  16.     public MiniSpanTree_PRIM(Graph_AdjMatrix g,String u)  //输入一个用领接矩阵表示的图和起始顶点  
  17.     {  
  18.         int k = g.getLocale(u);  
  19.         closedge = new Closedge[g.vertex.length];  
  20.         for(int i =0;i<g.vertex.length;i++)  
  21.         {  
  22.             if(i!=k){  
  23.                 closedge[i] = new Closedge(u,g.adjMatrix[k][i]);  
  24.             }  
  25.         }  
  26.         closedge[k] = new Closedge("",0);  
  27.         for(int i =1;i<g.vertex.length;i++)  
  28.         {  
  29.             k = mininum(closedge);  
  30.             System.out.println(closedge[k].vetex+","+g.vertex[k]);  
  31.             closedge[k].lowcost = 0;  
  32.             for(int j=0;j<g.vertex.length;j++)  
  33.             {  
  34.                 if(g.adjMatrix[k][j]<closedge[j].lowcost)  
  35.                 {  
  36.                     closedge[j].vetex = g.vertex[k];  
  37.                     closedge[j].lowcost = g.adjMatrix[k][j];  
  38.                 }  
  39.             }  
  40.         }  
  41.     }  
  42.       
  43.     private int mininum(Closedge[] array)  
  44.     {  
  45.         int weight =array[0].lowcost;  
  46.         int k=0;  
  47.         for(int i=1;i<array.length;i++)  
  48.         {  
  49.             if(array[i].lowcost==0)  
  50.                 continue;  
  51.             else  
  52.             {  
  53.                 if(weight==0)  
  54.                 {  
  55.                     weight = array[i].lowcost;  
  56.                     k =i;  
  57.                 }  
  58.                 else  
  59.                 {  
  60.                     if(array[i].lowcost<=weight)  
  61.                     {  
  62.                         weight = array[i].lowcost;  
  63.                         k = i;  
  64.                     }  
  65.                 }  
  66.             }  
  67.         }  
  68.         return k;  
  69.     }  
  70. }  

 

这只是一个表述Prim算法的类。若要是该算法为你构造最小生成树,那还需写一个驱动程序。注意该算法中输入的图是以邻接矩阵的数据结构进行存储的。

posted @ 2014-06-13 02:19  princessd8251  阅读(648)  评论(0)    收藏  举报