#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <limits.h>//
#define INFINITY INT_MAX//用整型最大值代替无穷大
#define MAX_VERTEX_NUM 20//最大的顶点的个数
#define MAX_NAME 3//定点字符串的最大长度+1
typedef int VRType;
typedef char VertexType[MAX_NAME];
typedef char InfoType;
//-------图的数组(邻接矩阵)存储表示-------
typedef enum
{
DG,DN,UDG,UDN//有向图,有向网,无向图,无向网
}GraphKind;
typedef struct ArcCell
{
VRType adj;// VRType是顶点关系类型,对无全图,用0或1,表示相邻否
//对带权图,则为权值类型
InfoType *info;//该弧的相关信息
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
VertexType vexs[MAX_VERTEX_NUM];//定点向量
AdjMatrix arcs;//邻接矩阵
int vexnum,arcnum;//图的当前定点数和弧数
GraphKind kind;//图的种类标志
}MGraph;
//记录从顶点U到v-U的代价最小的边的辅助数组定义
typedef struct
{
VertexType adjvex;
VRType lowcost;
}closedge[MAX_VERTEX_NUM];
//查询某个顶点的位置函数
int LocateVex(MGraph G,VertexType u)//此处u为顶点
{
int i;
for(i=0;i<G.vexnum;i++)
{
if(strcmp(u,G.vexs[i])==0)
return i;
}
if(i==G.vexnum)
{
printf("不存在该顶点!\n");
exit(1);
}
return 0;
}
//创建有向网
void CreatGraph(MGraph &G)
{
int i,j,k,adj;
char ch;
VertexType v1,v2;
printf("请输入要创建的图的顶点的个数和边的个数(以空格隔开):");
scanf("%d%d",&G.vexnum,&G.arcnum);
ch=getchar();//吸收回车符
printf("请输入顶点的值:\n");
for(i=0;i<G.vexnum;i++)
{
scanf("%s",&G.vexs[i]);//输入顶点的值
ch=getchar();
}
for(i=0;i<G.vexnum;i++)//先对整个邻接矩阵进行初始化
for(j=0;j<G.vexnum;j++)
{
G.arcs[i][j].adj=INFINITY;//权值为最大值
G.arcs[i][j].info=NULL;//顶点信息为空
}
printf("请输入图的弧的相关信息(v1,v2,adj即顶点1,顶点2,权值):\n");
for(k=0;k<G.arcnum;k++)//再根据输入的弧来更新邻接矩阵
{
scanf("%s%s%d",&v1,&v2,&adj);
ch=getchar();
i=LocateVex(G,v1);//找到顶点v1和v2的下表位置
j=LocateVex(G,v2);
G.arcs[i][j].adj=adj;//更新有关联的顶点的权值
}
}
//显示图的函数
void display(MGraph G)
{
int i,j;
if(G.vexnum==0)
printf("该图是个空图!\n");
for(i=0;i<G.vexnum;i++)
{
for(j=0;j<G.vexnum;j++)
{
printf("%d ",G.arcs[i][j].adj);
}
printf("\n");
}
}
//查询当前closedge.lowcost中最小的值
int minmum(closedge &S,MGraph G)
{
int i=0,j,k,min;
while(!S[i].lowcost)//不为0 的情况下
i++;
k=i;
min=S[i].lowcost;
for(j=i+1;j<G.vexnum;j++)
{
if(S[j].lowcost>0)
{
if(min>S[j].lowcost)
{
k=j;
min=S[j].lowcost;
}
}
}
return k;
}
//用普里姆算法从第u个顶点除法构造网G的最小生成树T,输出T的各条边
void MiniSpanTree_PRIM(MGraph G,VertexType u)
{
closedge min;
int k,j,i;
k=LocateVex(G,u);
for(j=0;j<G.vexnum;j++)//辅助数组初始化
{
if(j!=k)
{
strcpy(min[j].adjvex,G.vexs[k]);
min[j].lowcost=G.arcs[k][j].adj;
}
}
min[k].lowcost=0;//初始,U={u};
for(j=1;j<G.vexnum;j++)
{
k=minmum(min,G);//选择其余G.vexnum-1个顶点中与U集合中关联的权值最小的顶点
printf("%s--%s\n",min[k].adjvex,G.vexs[k]);//输出生成树的边
min[k].lowcost=0;//第k个顶点加入集合U
for(i=0;i<G.vexnum;i++)//对辅助数组的重新更新
{
if(G.arcs[k][i].adj<min[i].lowcost)
{
strcpy(min[i].adjvex,G.vexs[k]);
min[i].lowcost=G.arcs[k][i].adj;
}
}
}
}
int main()
{
MGraph G;
CreatGraph(G);//创建图
display(G);//显示图
MiniSpanTree_PRIM(G,G.vexs[0]);//普里姆算法求最小生成树
return 0;
}