Prim算法(加点法)
- Prim为求图最小生成树的算法
- 本文章采用邻接矩阵的存储方式
具体思路如下
- 1.首先以邻接矩阵方式输入图
- 2.进入算法函数
- 3.设置closedge数组辅助
- 4.先将一个start顶点加入生成树顶点集合中
- 5.用start顶点的边关系将closedge数组初始化
- 6.找出当前closedge没有进入生成树的顶点中lowcost最小值记为min,对应的顶点记为m
- 7.将m顶点加入到生成树顶点集合中
- 8.打印刚加入的顶点与权值最小边的信息
- 9.用m顶点的信息更新closedge数组的信息,如果发现更小的权值边出现,则替换原有信息
- 10.重复6-9直到找出n-1条边是结束
具体代码如下
/*prim算法(加点法),适合稠密图*/
#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 20 /*最大顶点个数*/
#define INFINITY 32767 /*表示无穷,可自定义*/
#define Elem int
#define FALSE 0
#define OK 1
#define TRUE 1
typedef char VertexType;
typedef struct{
int arcs[MAXVEX][MAXVEX]; //邻接矩阵,边的信息
VertexType vexs[MAXVEX]; //顶点信息
int vexnum; //顶点数目
int arcnum; //边(弧)数目
}AdjMatrix;
typedef struct{ //数组元素的下标对应图G的顶点序号
int adjvex; /*记录该顶点和顶点集合中相连权值最小的顶点序号*/
int lowcost; /*记录最小的权值*/
}Closedge;
//根据名称得到指定顶点在顶点集合中的下标
int getIndexOfVexs(char vex,AdjMatrix *MG)
{
for(int i=1;i<=MG->vexnum;i++)
{
if(MG->vexs[i]==vex) return i;
}
return 0;
}
//用邻接矩阵创建图
void Create(AdjMatrix *MG){
int v1,v2;
char c1,c2;
printf("请输入顶点数目: "); //输入顶点数
scanf("%d",&MG->vexnum);
printf("请输入边的数目: "); //输入边数
scanf("%d",&MG->arcnum);
getchar();
//输入各顶点信息
for(int i=1;i<=MG->vexnum;i++)
{
printf("请输入第%d个顶点(char): ",i); //请输入各顶点信息
scanf("%c",&MG->vexs[i]);
getchar();
}
//初始化邻接矩阵
for(int i=1;i<=MG->vexnum;i++)
for (int j=1;j<=MG->vexnum;j++)
MG->arcs[i][j]=INFINITY; /*如果是网则赋值INFINITY */
//输入边的信息,建立邻接矩阵
for(int k=1;k<=MG->arcnum;k++)
{
printf("请输入第%d个边连接的两个顶点及权值v1(char) v2(char) weight(int): ",k); //请输入有关系的两个顶点
int weight=INFINITY;
scanf("%c %c %d",&c1,&c2,&weight);
v1=getIndexOfVexs(c1,MG);
v2=getIndexOfVexs(c2,MG);
MG->arcs[v1][v2]=weight;
MG->arcs[v2][v1]=weight; //无向图为对称矩阵
getchar();
}
}
//打印图的信息
void Printf(AdjMatrix MG)
{
printf("顶点数目为: %d\n",MG.vexnum);
printf("边的数目为: %d\n",MG.arcnum);
printf("顶点: ");
for(int i=1;i<=MG.vexnum;i++)
printf("%c",MG.vexs[i]);
printf("\n邻接矩阵为: \n");
for(int i=1;i<=MG.vexnum;i++)
{
for(int j=1;j<=MG.vexnum;j++){
if(MG.arcs[i][j]==INFINITY) printf("#");
else printf("%d",MG.arcs[i][j]);
}
printf("\n");
}
}
/****************最小生成树(Prim算法)***************/
void Prim(AdjMatrix G,int start){
Closedge closedge[MAXVEX];
closedge[start].lowcost=0; /*标志顶点加入到生成树集合中*/
//初始化剩下的所有顶点对应的closedge数组
for(int i=1;i<=G.vexnum;i++){
if(i!=start){
closedge[i].adjvex=start;
closedge[i].lowcost=G.arcs[start][i];
}
}
printf("\n最小生成树的生成过程:");
//从边集中选出n-1条符合条件的边
for(int e=1;e<=G.vexnum-1;e++){
int m; //记录顶点
int min=INFINITY; //记录最小权值
//找出当前closedge没有进入生成树的顶点中lowcost最小值对应的顶点
for(int k=1;k<=G.vexnum;k++){
if((closedge[k].lowcost!=0)&&closedge[k].lowcost<min){
min=closedge[k].lowcost;
m=k;
}
}
printf("\n(%c,%c) %d",G.vexs[closedge[m].adjvex],G.vexs[m],min);
closedge[m].lowcost=0; /*标志顶点m进入生成树集合*/
//用新的生成树顶点m,更新closedge数组
for(int i=1;i<=G.vexnum;i++){
if((closedge[i].lowcost!=0)&&G.arcs[m][i]<closedge[i].lowcost){
//如果发现有更小的权值边出现,则替换原有信息
closedge[i].lowcost=G.arcs[m][i];
closedge[i].adjvex=m;
}
}
}
}
int main(){
AdjMatrix MG,T;
Create(&MG);
Prim(MG,1);
return 0;
}