zoukankan      html  css  js  c++  java
  • 最小生成树的Prim算法

       构造最小生成树的Prim算法
       假设G=(V,E)为一连通网,其中V为网中所有顶点的集合,E为网中所有带权边的集合。设置两个新的集合U和T,其中集合U用于存放G的最小生成树的顶点,集合T用于存放G的最小生成树中的边。令集合U的初值为U={u0}(假设构造最小生成树时是从顶点u0出发),集合T的初值为T={}。Prim算法的思想是:在连通网中寻找一个顶点落入U集,另外一个顶点落入V-U集的这个顶点加入到U集中,然后继续寻找一顶点在U集而另一顶点在V-U集且权值最小的边放入T集;如果不断重复直到U=V时,最小生成树就已经生成,这时集合T中包含了最小生成树的所有边。
     
    概述:
        为实现Prim算法,需要设置两个一维数组lowcost和closevertex;其中,数组lowcost用来保存集合V-U中各顶点与集合U中各顶点所构成的边中具有最小权值的边的权值,并且一旦将lowcost[i]置为0,则表示顶点i已加入到集合U中,即该顶点不再作为寻找下一个最小权值边的顶点(只能在V-U集合寻找),否则将形成回路;也即,数组lowcost有两个功能:一是记录边的权值,二是标识U集中的顶点。数组closevertex也有两个功能:一是用来保存依附于该边在集合U中的顶点,即若closevertex[i]的值为j,则表示边(i,j)中的顶点j在集合U中;二是保存构造最小生成树过程中产生的每一条边,如closevertex[i]的值为j,则表示边(i,j)是最小生成树的一条边。
        我们先设定初始状态U={u0}(u0为出发的顶点),这时置lowcost[0]为0则表示顶点u0已加入到U集中,数组lowcost其它的数组元素值则为顶点u0到其余各顶点边的权值(没有边相连则取一个极大值),同时初始化数组closevertex[i]所有数组元素值为0(即先假定所有顶点包括u0都与u0有一条边).然后不断选取权值最小的边(ui,uk)(ui->U,uk->V-U),每选取一条边就将lowlost[k]置为0,表示顶点uk已加入到集合U中.由于uk从集合V-U进入到集合U,故这两个集合中的顶点发生了变化,所以需要依据这些变化修改数组lowcost和数组closevertex中相关内容.最终数组closevertex中的边即构成一个最小生成树。

    参考代码:
     1 #include<stdio.h>
     2 #define MAXNODE 30
     3 #define MAXCOST 32767
     4 
     5 void Prim(int gm[][6],int closevertex[],int n)//从存储序号为0的顶点出发建立连通网的最小生成树,gm是邻接矩阵,n为顶点个数,最终建立最小生成树存于数组closevertex中
     6 {
     7     int lowcost[MAXNODE];
     8     int i,j,k,mincost;
     9     for(i=1;i<n;i++)//初始化
    10     {
    11         lowcost[i]=gm[0][i];//边(u0,ui)的权值送lowcost[i]
    12         closevertex[i]=0;//假定顶点ui到顶点u0有一条边
    13     }
    14     lowcost[0]=0;//从序号为0的顶点u0出发生成最小生成树,此时u0已经进入U集
    15     closevertex[0]=0;
    16     for(i=1;i<n;i++)//在n个顶点中生成有n-1条边的最小生成树(共n-1趟)
    17     {
    18         mincost=MAXCOST;//MOXCOST为一个极大的常量值
    19         j=1;k=0;
    20         while(j<n)//寻找未找到过的最小权值边
    21         {
    22             if(lowcost[j]!=0&&lowcost[j]<mincost)
    23             {
    24                 mincost=lowcost[j];//记下最小权值边的权值
    25                 k=j;//记下最小权值边在V-U集中的顶点序号
    26 
    27             }
    28             j++;//继续寻找
    29         }
    30         printf("Edge:(%d,%d),Wight:%d
    ",k,closevertex[k],mincost);//输出最小生成树的边与权值
    31         lowcost[k]=0;//顶点k进入U集
    32         for(j=1;j<n;j++)
    33             if(lowcost[j]!=0&&gm[k][j]<lowcost[j])//若顶点k进入U集后使顶点k与另一顶点j(在V-U集中)构成的边权值
    34             {                                     //变小则改变lowcost[j]为这个小值,并将此最小权值的边(j,k)记入closevertex数组
    35                 lowcost[j]=gm[k][j];
    36                 closevertex[j]=k;
    37             }
    38     }
    39 }
    40 
    41 void main()
    42 {
    43     int closevertex[MAXNODE];//存放最小生成树所有边的数组
    44     int g[6][6]={{100,6,1,5,100,100},{6,100,5,100,3,100},{1,5,100,5,6,4},
    45     {5,100,5,100,100,2},{100,3,6,100,100,6},{100,100,4,2,6,100}};
    46     Prim(g,closevertex,6);//生成最小生成树
    47 }


    输出:


    连接图和对应邻接矩阵如下:


    执行Prim算法产生最小生成树的分析过程见表,“---"标记的权值为每一趟所找到的最小权值。图中最小生成树每一步生长示意a~f分别对应表中的(1)~(6)趟:(1)为初始状态,(2)到(6)为生成n-1条边的n-1趟生长过程。


        
    最小生成树的每一步生长情况如下图所示。其中带阴影的顶点属于U集,不带阴影的顶点属于V-U集;虚线边为待查的满足一顶点属于U集而另一顶点属于V-U集的边,而实线边则为已找到的最小生成树中的边。


  • 相关阅读:
    C#学习历程(三)[基础概念]
    C#学习历程(二)[基础知识]
    C#学习历程(一)[基础概念]
    mvp和mvc的区别
    Java基础摘要(一)
    web前端概念摘要(一)
    Reflection_1
    后台管理_GMS_1
    模板收藏_1
    需求收藏_1
  • 原文地址:https://www.cnblogs.com/wxdjss/p/5501127.html
Copyright © 2011-2022 走看看