#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define VexMAx 100//最大顶点数为100
#define MaxInt 9999//表示最大整数,表示 ∞
typedef struct{
int no;
char info;
}Vertex;
typedef struct{
int AdjMatrix[VexMAx][VexMAx];
int vexnum,arcnum;
Vertex vexs[VexMAx];
}MGraph;
typedef struct{//辅助数组结构体(候选最短边)
Vertex adjvex;//候选最短边的邻接点
int lowcost;//候选最短边的权值
}ShortEdge;
void CreateAdjMatrix(MGraph *G);
int LocateVex(MGraph *G,Vertex v);
void print(MGraph G);
void MiniSpanTree_Prim(MGraph *G,Vertex start);
int main(){
MGraph G;
CreateAdjMatrix(&G);
print(G);
printf("请输入起始点:");Vertex start;
scanf("%c",&start.info);
MiniSpanTree_Prim(&G,start);
}
void CreateAdjMatrix(MGraph *G){//构造以邻接矩阵为存储结构的无向图
printf("输入顶点个数和边数:\n");
printf("顶点数 n=");
scanf("%d",&G->vexnum);
printf("边 数 e=");
scanf("%d",&G->arcnum);
printf("\nvexnum=%d\n",G->vexnum);
//2.输入顶点元素
printf("输入顶点元素:");
for(int k=0;k<G->vexnum;k++){
printf("%d是 ",k);
scanf("%c",&G->vexs[k].info);
G->vexs[k].info=getchar();
}
for(int i=0;i<G->vexnum;i++){
printf("%c",G->vexs[i].info);
}
//3.矩阵初始化
for(int i=0;i<G->vexnum;i++)
for(int j=0;j<G->vexnum;j++){
G->AdjMatrix[i][j]=MaxInt;
}
//4.构建邻接矩阵
int a,b,weight;//v1->v2的权值
Vertex v1,v2;
printf("请输入边的信息和权值(a b 9):\n");
for(int i=0;i<G->arcnum;i++){
scanf("%c %c %d",&v1.info,&v2.info,&weight);
//printf("\nv1.info=%c v2.info=%c weight=%d\n",v1.info,v2.info,weight);
a=LocateVex(G,v1); //获取v1所对应的在Vertex数组中的坐标
b=LocateVex(G,v2); //获取v2所对应的在Vertex数组中的坐标
if(a==-1||b==-1)printf("NO This Vertex!\n");
}
G->AdjMatrix[a][b]=weight;
G->AdjMatrix[b][a]=weight;//无向网仅此处不同
}
int LocateVex(MGraph *G,Vertex v1){//查找元素v在一维数组 Vertex[] 中的下标,并返回下标
int flag=-1;
for(int i=0;i<G->vexnum;i++){
if(v1.info==G->vexs[i].info)flag=i;
}
return flag;
}
void print(MGraph G){
int i,j;
printf("\n-------------------------------");
printf("\n 邻接矩阵:\n\n");
printf("\t ");
for(i=0;i<G.vexnum;i++)
printf("\t%c",G.vexs[i]);
printf("\n");
for(i=0;i<G.vexnum;i++){
printf("\t%c",G.vexs[i]);
for(j=0;j<G.vexnum;j++){
if(G.AdjMatrix[i][j]==MaxInt) printf("\t∞");
else printf("\t%d",G.AdjMatrix[i][j]);
}
printf("\n");
}
}
void MiniSpanTree_Prim(MGraph *G,Vertex start){
ShortEdge ShortEdge[VexMAx];
int vset[G->vexnum];//辅助数组记录顶点位置未访问0访问1
int k=LocateVex(G,start);//定位初始点的位置
for(int i=0;i<G->vexnum;i++){
if(i!=k){//非k的顶点放入v-u的集合
ShortEdge[i].adjvex=start;//候选最短边的邻接点初置为start
ShortEdge[i].lowcost=G->AdjMatrix[k][i];
vset[i]=0;
}
}
vset[k]=1;//lowcost为1表示该顶点属于U集合
for(int i=0;i<G->vexnum;i++){//找最短路径的顶点
int min=-1;
for(int j=0;j<G->vexnum;j++){
if(vset[j]!=1&&ShortEdge[j].lowcost<min){
min=ShortEdge[j].lowcost;
k=j;//求出T的下一个结点:第k个结点
}
}
vset[k]=1;//第k个定点并入U集合
for(int j=0;j<G->vexnum;j++){//有更短路径出现时,将其替换进shortedge数组
if((vset[j]==0)&&(G->AdjMatrix[k][j]<ShortEdge[j].lowcost)){//有更短路径出现时,将其替换进shortedge数组
ShortEdge[j].adjvex=G->vexs[k];
ShortEdge[j].lowcost=G->AdjMatrix[k][j];
}
}
}
}