最小生成树 普莱姆(prim)算法

  文章作者:ktyanny 文章来源:ktyanny 转载请注明,谢谢合作。  

   

  ktyanny最近很心烦,因为前天兴致勃勃想写个prim算法,结果很郁闷,看了两下也没想到怎么实现,囧了半天放弃了…… 但是还是不死心呐,一大早起来,不对劲,怎么舍友全走了,原来我已经睡过了两节课了,要不是肚子饿了的话我可能还会继续睡下去的。那就待会去上三四节的os课吧,先打开电脑去农场看菜回来,哇咔咔,好多菜可以摘啊,看来起床时是摘菜的最佳时间呐。

  从农场拿了个大丰收回来,又想起心里那个结还没了断,又拿起算法导论左看右看的,还是没感觉,汗……突然想起严蔚敏阿姨那本数据结构,诶,写得倒是蛮详细的,仔细数了一下,嘿嘿,13行代码,小case,嘎嘎……二话不说看完,恍然大悟中,上os课的时候,就拿起算法导论的那个图左画右画的,就是下面这个图:(在这里强调一下,如果你不知道最小生成树的概念,可以点击最小生成树 Kruscal经典算法查看最小生成树得到概念和性质)

 

 

   上面的这个图是个很好的例子,其实不用不明白,这个图的最小生成树是不唯一的,认真思考就知道为什么了。

  留念一下os课上的我的鬼画虎的作品哈哈……(没带相机,吃完饭回到宿舍拍的)

 

   好了,流水账就记录那么多了。

   普里姆算法的基本思想:

  从连通网络 N = { V, E }中的某一顶点 u0 出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把它的顶点加入到集合U中。如此继续下去,直到网络中的所有顶点都加入到生成树顶点集合U中为止。

 

  Prim算法的形式描述如下:


    置T为任意一个顶点;
    求初始候选边集;
    
while (T中结点数<n)
     {
    从候选边集中选取最短边(u,v);
     将(u,v)及顶点v,扩充到T中;
    调整候选边集;
      }

 

   

  为了更方便了解,贴上几个刚刚拍下来的prim算法过程的图片吧

 

   好吧,就这样吧。

  下面是写得很辛苦的代码:

/*
by ktyanny
2009.12.15
*/
#include 
< stdio.h >
#include 
< stdlib.h >
#include 
< iostream >
using   namespace  std;

const   int  MAXN  =   0x7fffffff ;
const   int  MAX  =   105 ;     /* 顶点上限 */
typedef 
int  vrtype;

vrtype g[MAX][MAX];    
/* 图的带权邻接矩阵 */

vrtype prim(vrtype g[][MAX], 
int  n)
{
    
int  i, j, k, minn, closest[MAX], ans  =   0 ;
    vrtype lowcost[MAX];
    
for (i  =   2 ; i  <=  n; i ++ )
    {
        lowcost[i] 
=  g[ 1 ][i];
        closest[i] 
=   1 ;
    }

    closest[
1 =   0 ;     /* 第一个节点是在U集合里的 */

    
for (i  =   2 ; i  <=  n; i ++ )
    {
        minn 
=  MAXN;
        k 
=  i;
        
for (j  =   1 ; j  <=  n; j ++ )
        {
            
if (lowcost[j]  <  minn  &&  closest[j]  !=   0 )
            {
                minn 
=  lowcost[j];
                k 
=  j;
            }
        }
        
/*
        打印边        
        printf("(%c, %c)", closest[k], k);    
        
*/

        ans 
+=  minn;
        closest[k] 
=   0 ; /* k并入U集合 */

        
for (j  =   2 ; j  <=  n; j ++ )
        {
            
if (closest[j]  &&  g[k][j]  <  lowcost[j])
            {
                lowcost[j] 
=  g[k][j]; /* 更新最小权值 */
                closest[j] 
=  k;  /* 记录新的起点 */
            }
        }
    }
    
return  ans;
}

 

 

   

转载于:https://www.cnblogs.com/ktyanny/archive/2009/12/15/1625020.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值