图-最小生成树-Prim

普利姆算法(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

说明:

  • adjvex数组存放的是对应顶点的前驱,即当选定v2为权最小加入最小生成树时,adjvex[2]=0.在代码的一开始adjvex全部置为0,因为v0的算法起始点。
  • lowcost置为0时表示的时已经将对应顶点加入最小生成树,比如lowcost[0]=0,即表示生成树集合U=为{V0},当然了,当U=V(顶点集)时,算法结束。
  • 这里很多循环是从1开始的,因为v0已经被加入了U集(lowcost[0]=0),从0开始浪费一次循环,当然如果从0开始也不会报错。注意第一个for循环是在初始化v0到其他各顶点的权值,从i=1开始时因为从v0到v0的边没有意义,当然了如果你把对角线设置为0的话,其实从0开始也没区别。
  • 在第一次for循环里,初始化所有顶点对应adjvex都为0,因为从0开始找最小权值,找到了的话他的前驱一定也只能是v0。
#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*/
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。