算法介绍
普利姆算法是一种图算法,用于构建最小生成树。最小生成树的顶点全部连通,即沿任意顶点出发,可以达到图的全部顶点,且其所有边的权值最小。
算法描述:
从最小生成树集合中选择边权值最小且不在生成树集合中的顶点加入最小生成树集合,重复上述操作直到全部的点加入最小生成树集合。
算法实现
现有5个村落(编号为0-4)需要在各个村庄中修路,使各村庄联通,且代价最小。
这里我们使用邻接矩阵来表示上图
普利姆算法执行过程
实现普利姆算法需要利用两个辅助数组lowcost和edge。
lowcost数组用于保存最小生成树集合到各顶点的距离,数组索引与顶点相关联。l例如owcost[3]表示最小生成树集合到顶点4的距离
如果数组中元素值为0则表示顶点存在于最小生成树集合,否则表示权值大小。
edge用于存储顶点的边关系,edge[1]=2表示与节点1与节点2相连。
1 2
| int lowcost[graph->vexnum]; int edge[graph->vexnum];
|
执行过程:
选定一个节点加入最小生成树集合,初始化lowcost和edge数组
重复下面3的步骤,直到所有的顶点都加入最小生成树集合
选择lowcost数组中权值最小的顶点,加入最小生成树集合,利用新加入的顶点更新lowcost数组和edge数组
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| int lowcost[graph->vexnum]; int edge[graph->vexnum];
for(int i=0;i<graph->vexnum;i++){ lowcost[i]=graph->matrix[0][i]; edge[i]=start; } lowcost[start]=0; for(int i=1;i<graph->vexnum;i++){ int min=1024; int minindex=-1; for(int j=0;j<graph->vexnum;j++){ if(lowcost[j]<min&&lowcost[j]!=0){ min=lowcost[j]; minindex=j; } } lowcost[minindex]=0; printf("边(%d,%d)的权值为%d\n",edge[minindex],minindex,min); for(int j=0;j<graph->vexnum;j++) if(lowcost[j]>graph->matrix[minindex][j]){ lowcost[j]=graph->matrix[minindex][j]; edge[j]=minindex; } } }
|
这里我们选择顶点0加入最小生成树结合,
lowcost数组值为最小生成树集合到各顶点的距离,由于集合中只有顶点V0,所以lowcost[0]被设置为了0,其余值为设置为顶点0到其余点的距离。edge数组被初始化为0,表示顶点0与其他边相连。
1 2 3 4 5 6 7 8
| int lowcost[graph->vexnum]; int edge[graph->vexnum];
for(int i=0;i<graph->vexnum;i++){ lowcost[i]=graph->matrix[0][i]; edge[i]=start; } lowcost[start]=0;
|
之后遍历lowcost数组找到最小权值1和对应顶点V1,选择V1加入最小生成树集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| for(int i=1;i<graph->vexnum;i++){ int min=1024; int minindex=-1; for(int j=0;j<graph->vexnum;j++){ if(lowcost[j]<min&&lowcost[j]!=0){ min=lowcost[j]; minindex=j; } } lowcost[minindex]=0; }
|
V1加入集合后,遍历与V1相邻的边,如果边的权值<对应owcost的权值,则更新lowcost和edge
1 2 3 4 5
| for(int j=0;j<graph->vexnum;j++) if(lowcost[j]>graph->matrix[minindex][j]){ lowcost[j]=graph->matrix[minindex][j]; edge[j]=minindex; }
|
重复上面的步骤,选择顶点2加入最小生成树集合,V2邻边距离均大于lowcost数组值,lowcost数组不更新
选择V3加入最小生成树集合,更新lowcost[4]的值,以及egde[4]的值
选择V4加入集合
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| void Prim(Graph *graph,int start){
int lowcost[graph->vexnum]; int edge[graph->vexnum];
for(int i=0;i<graph->vexnum;i++){ lowcost[i]=graph->matrix[0][i]; edge[i]=start; }
lowcost[start]=0;
for(int i=1;i<graph->vexnum;i++){ int min=1024; int minindex=-1; for(int j=0;j<graph->vexnum;j++){ if(lowcost[j]<min&&lowcost[j]!=0){ min=lowcost[j]; minindex=j; } } lowcost[minindex]=0; printf("边(%d,%d)的权值为%d\n",edge[minindex],minindex,min); for(int j=0;j<graph->vexnum;j++) if(lowcost[j]>graph->matrix[minindex][j]){ lowcost[j]=graph->matrix[minindex][j]; edge[j]=minindex; } } }
|
运行结果