无向连通网的最小生成树

对于一个无向网(即带权无向图),生成树上各边权值之和称作这棵生成树的代价,最小代价生成树是各边权值综合最小的生成树,简称最小生成树。

一个无向连通网的最小生成树也可能不是惟一的,但总代价一定是最小的。构造无向连通网的最小生成树方法可以有多种,下面介绍Prim和Kruskal算法就是构造最小生成树的两种算法。

1.prim算法

prim算法是从连通网中的某一个顶点开始,以此作为生成树的初始状态,然后不断地将网中的其他顶点添加到生成树上,直到最后一个顶点添加到生成树上时得到最小生成树,其具体方法是:

(1).从网中的任一顶点开始,先把该顶点包含在生成树中,此时生成树只有一个顶点。
(2).找出一个端点在生成树中,另一个在生成树外的所有边,并把权值最小的边连同它所关联的另一个顶点添加到生成树中;当有两条及以上具有相同最小权值的边可供选择时,选择其中任意一条都可以。
(3).反复执行(2),直到所有顶点都包含在生成树中时止。
为了实现Prim算法,须设一个辅助数组closedge以记录每次选择的权值最小的边。数组元素closedge[i]对应于序号为i的顶点Vi,它包含两个域adjvex和lowcost.若Vi已在生成树上,则置closedge.lowcost=0;
若顶点Vi不在生成树上,用closedge[i].lowcost存放Vi与生成树上顶点构成的最小代价边的权值,而closedge[i].adjvex存放该边所关联的生成树上的另一顶点的序号。
设有n个顶点的无向连通图以邻接矩阵g存储,从序号为k的顶点Vk开始构造最小生成树,则辅助数组的初始情况为:
closedge[k].lowcost=0;
closedge[k].lowcost=g.adjmatrix[k,i];(i!=k且1<=i<=n)
closedge[k].adjvex=k;(i!=k且1<=i<=n)
然后从数组选出某一个j,它满足closedge[i].lowcost不等于0且是最小的值,将Vj添加到生成树上并修改closedge数组的值。如此不断进行下去,直到
全部的n个顶点都在生成树上,就得到了要求的最小生成树。下面给出Prim算法的形式化描述如下:


#define m 30//m为顶点的个数最大值
#define max 99//max为权上次上限值
void prim(mgraph g,int k,int n)//从顶点Vk出发构造有n个顶点的无向连通网g的最小生成树的Prim
{
    int i,j,min,p;
    struct{
              int adjvex;//定义序号域为整型
              int lowcost;//假定权值均为整型数
          }closedge[m];//定义辅助数组的基类型为结构体
    for(i=1;i<=n;i++)//辅助数组初始化
        if(i!=k)
        {
            closedge[i].adjvex=k;//填边在生成树一端的顶点序号
            closedge[i].lowcost=g.adjmatrix[k][i];//填边的权值
        }
    closedge[k].lowcost=0;//顶点Vk已在生成树中,修改辅助数组
    for(i=1;i

2.Kruskal算法

Kruskal算法是求无向连通网的最小生成树的另一种常用算法。它与prim算法不同,时间复杂度主要是与网中边的数量e相关为O(eloge),适用于求边稀疏的无向连通网的最小生成树。

Kruskal算法的思想为:

(1).将n个顶点看作是n个独立的连通分量,将e条边按权值大小由小到大排序。

(2).从权值最小的边开始依权值递增顺序查看每一条边,如果该边所依附的两个顶点在两个不同的连通分量上,则选定此边连接两个连通分量为一个连通分量,否则舍弃此边。

(3).反复执行(2),直到所有顶点都在同一个连通分量上为止,这个连通分量即所求的最小生成树。

你可能感兴趣的:(数据结构知识汇总)