#include <stdio.h>
#include <stdlib.h>
#define MAX 100
#define INFINITY 10000
typedef struct graph{
char vexs[MAX]; //顶点集合
int vexnum; // 顶点数
int arcnum; // 边数
int arc[MAX][MAX]; //邻接矩阵
int visited[MAX];//设置访问数组
}MGraph,*PGraph;
typedef struct{
int adjvertex;
int lowcost;
}CloseEdge[MAX];//PRIM算法的核心结构体
void create_graph(PGraph G){
int i,j,k,w;
printf("请输入顶点数和边数:");
scanf("%d%d",&G->vexnum,&G->arcnum);
getchar();
for(i=0;i<G->vexnum;i++){
printf("请输入%d个顶点的信息\n",i+1);
scanf("%c",&G->vexs[i]);
getchar();
}
//邻接矩阵的初始化,对角线为0,其他地方为infinity
for(i=0;i<G->vexnum;i++){
for (j=0; j<G->vexnum; j++) {
if(i==j)
G->arc[i][j] = 0;
else
G->arc[i][j] = INFINITY;
}
G->visited[i] = 0;
}
//对邻接矩阵进行赋值
for(k=0;k<G->arcnum;k++){
printf("输入边(vi,vj)的下标i,j以及权值w:");
scanf("%d%d%d",&i,&j,&w);
G->arc[i][j] = w;
G->arc[j][i] = w;
}
}
void MiniSpanTree_PRIM(MGraph *G, int u,CloseEdge closedge){
//u为起点
int i,j,w,k;
int count=0;
//初始化工作,lowcost中存入当前节点到其他节点的权值
for(i=0;i<G->vexnum;i++){
if(i!=u){
closedge[i].adjvertex=u;//邻接点为u
closedge[i].lowcost=G->arc[u][i];//将u与i的权值存入lowcost
}
}
closedge[u].lowcost = 0;//访问过的u则lowcost=0,通过此标记便不再访问u;
//寻找权值最小的顶点
for(i=0;i<G->vexnum;i++){
w=INFINITY;
//第一个内循环得到权值最小顶点
for(j=0;j<G->vexnum;j++){
if(closedge[j].lowcost!=0&&closedge[j].lowcost<w){
w=closedge[j].lowcost;
k=j;
}
}//查询到到已经访问顶点距离最近的顶点k
closedge[k].lowcost=0;//访问过的节点标记为0;
//接下来也是该算法的精髓,比较新找到节点与j的权值是否比原先lowcost小,小的话则进行替换。
for(j=0;j<G->vexnum;j++){
if(G->arc[k][j]<closedge[j].lowcost){
//更新操作
closedge[j].adjvertex=k;
closedge[j].lowcost=G->arc[k][j];
}
}
}// 外循环结束
//输出操作,就可以自己随意设计输出了.
for(i=0;i<G->vexnum;i++)
if(i!=u){
printf("输出构建的最小生成树为:");
printf("%c->%c,%d\n",G->vexs[i],G->vexs[closedge[i].adjvertex],G->arc[i][closedge[i].adjvertex]);//输出最短路径相关顶点信息以及他们之间的权值
count+=G->arc[i][closedge[i].adjvertex];
}
printf("\n");
printf("此最小生成树的总权值为:%d",count);
printf("\n");
}
int main(){
MGraph G;
CloseEdge a[MAX];
create_graph(&G);
MiniSpanTree_PRIM(&G,0,a[99]);
}
普利姆算法实现最小生成树(C语言版)
最新推荐文章于 2023-05-24 17:29:22 发布