前言
Prim算法在求最小生成树上的一个典型算法
声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出
实现思想
- 设置两个集合,U集合(在生成树中的结点),V-U集合(不在生成树中的图节点)
- 选择一个结点作为生成树的结点,并放入U集合
- 找到与根节点相连权值最小且不在U集合中结点,并加入到U中
- 重复操作n-1次
代码实现
#include <stdio.h>
//最大顶点数
#define MAX 100
//代表无穷大
#define M 32767
/*=============Prim算法实现=========*/
/*
使用两个辅助数组lowcost和closet
lowcost:保存最小权值信息
closet:保存依附在集合U中的顶点
*/
//生成无向网的邻接矩阵算法
int Creatcost(int cost[][MAX]){
//vnum:顶点数;anum:边数
int vnum,anum,i,j,k,v1,v2,w;
printf("请输入顶点数和边数(空格间隔):");
scanf("%d%d",&vnum,&anum);
for(i=0;i<vnum;i++)
for(j=0;j<vnum;j++)
cost[i][j]=M; //预设定矩阵中的各值为最大值
printf("输入各边及权值(顶点从1开始)\n");
for(k=0;k<anum;k++){
printf("v1 v2 w:");
scanf("%d%d%d",&v1,&v2,&w);
cost[v1][v2]=w; //将(w1,w2)设权值为w
cost[v2][v1]=w; //无向图将(w2,w1)设权值为w
}
return vnum;
}
void Prim(int c[MAX][MAX],int n){
/* 已知图的顶点为{0,1,...n-1},c[i][j]和c[j][i]为边(i,j)的权,打印最小生成树的每条边
*/
int i,j,k,min,lowcost[MAX],closetst[MAX];
for(i=1;i<n;i++){ //从顶点0开始
lowcost[i]=c[0][i]; //将lowcast数组中的各元素设为从0到各个顶点的权值
closetst[i]=0; //依附于该边的顶点为0
}
closetst[0]=-1; //标准0为起始点
for(i=1;i<n;i++){ //从U之外求离U中最近的顶点
min=M;k=i;
for(j=0;j<n;j++){
if(lowcost[j]<min&&closetst[j]!=-1){
min=lowcost[j]; //最小值设为当前权值
k=j; //此边依附顶点赋为j
}
}
//打印生成树改变及权值
printf("(%d,%d)权值%d\n",closetst[k],k,lowcost[k]);
closetst[k]=-1; //k加入u中
for(j=1;j<n;j++){
if(closetst[j]!=-1&&c[k][j]<lowcost[j]){
lowcost[j]=c[k][j];
closetst[j]=k;
}
}
}
}
int main(){
int n; //顶点个数
int cost[MAX][MAX];
n=Creatcost(cost);
printf("\n最小生成树\n");
Prim(cost,n);
}
结果图
而塞过 2021-5-16
关于我:一个就要进入互联网,经历社会毒打的99小伙