最小生成树(普里姆算法)
来源:互联网 发布:如何关闭阿里云盾 编辑:程序博客网 时间:2024/05/23 17:44
#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//定点字符串的最大长度+1typedef 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个顶点加入集合Ufor(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;}