图-最小生成树-Prim

2020-08-11  本文已影响0人  如春天

普利姆算法(Prim)

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;

3).重复下列操作,直到Vnew = V:

a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;

4).输出:使用集合Vnew和Enew来描述所得到的最小生成树

示例:

EXP.png

说明:

#include "邻接矩阵.h"
#define INFINITY 65535
void Prim(MGraph G){
    int min, i, j, k; /*k为最小值对应的下标*/
    int adjvex[MAXVEX]; /*保存的是每次循环开始的那个起始点下标*/
    int lowcost[MAXVEX];/*表示相关顶点之间的权值*/
    lowcost[0] = 0; /*表示下标为0的顶点即V0已经加入最小生成树*/
    adjvex[0] = 0; /*从顶点V0开始*/
    for(i = 1; i < G.numVertexes; i++){
        lowcost[i] = G.arc[0][i];/*将与V0顶点有边的顶点全部存入数组*/
        adjvex[i] = 0; /*全部初始化为V0的下标0*/

    }
    /*至此完成初始化工作 开始循环构造最小生成树*/
    for(i = 1; 1 < G.numVertexes; i++){
        min = INFINITY; /*初始化最小值为∞*/
        j = 1; k = 0;
        /*从1开始的原因已经在上面说明部分指出了,因为从0开始没有意义,V0已经在U集里了*/
        /*这个while循环每次从更新过的lowcost数组中找出了为0(即已经加入最小生成树)的最小值,找到之后对应的数组索引就是下一个要加入U集的顶点,把它赋给k*/
        while(j < G.numVertexes){
            if(lowcost[j]!=0 && lowcost[j] < min){
                /*如果权值不为0(尚未被纳入最小生成树)且权值小于min*/
                min = lowcost[j];
                k = j;
            }
            j++;
        }
        printf("(%d %d)", adjvex[k], k);/*打印当前顶点边中权值最小的边*/
        lowcost[k] = 0; /*k顶点已经被纳入最小生成树*/
        /*更新 新起始点到各顶点之间的权值 起始点已经从0变掉了,所以应该比较从0到各顶点的权值与从新起始点到各顶点的权值,取小者*/
        for(j = 1; j < G.numVertexes; j++){
            if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j])
                lowcost[j] = G.arc[k][j];
                adjvex[j] = k; /*同样的,更新对应的起始点下标,如果值更新比如v2->v4对应权值由v0->v4的xxx更新为更小的为yyy,则adjvex[4]=2;如果值没有更新的话,比如v0->v3权值还是更小的那一个,那他的adjvex也不更新,还是adjvex[3]=0,表示他的起始顶点为v0*/
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读