学习比较痛苦的一个普里姆算法,别废话了!上码如下:
/* 名称:普里姆算法 语言:数据结构C语言版 编译环境:VC++ 6.0 日期:2014-3-25 */ #include <stdio.h> #include <limits.h> #include <malloc.h> #include<cstdlib> #include <string.h> #define MAX_VERTEX_NUM 20 // 最大顶点个数 #define MAX_NAME 3 // 顶点字符串的最大长度+1 #define MAX_INFO 20 // 相关信息字符串的最大长度+1 #define INFINITY INT_MAX // 用整型最大值代替∞ typedef int VRType; typedef char InfoType; typedef char VertexType[MAX_NAME]; // 邻接矩阵的数据结构 typedef struct { VRType adj; // 顶点关系类型。对无权图,用1(是)或0(否)表示相邻否; // 对带权图,则为权值类型 InfoType *info; // 该弧相关信息的指针(可无) }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; // 图的数据结构 typedef struct { VertexType vexs[MAX_VERTEX_NUM]; // 顶点向量 AdjMatrix arcs; // 邻接矩阵 int vexnum,// 图的当前顶点数 arcnum; // 图的当前弧数 } MGraph; // 记录从顶点集U到V-U的代价最小的边的辅助数组定义 typedef struct { VertexType adjvex; VRType lowcost; }minside[MAX_VERTEX_NUM]; // 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。 int LocateVex(MGraph G,VertexType u) { int i; for(i = 0; i < G.vexnum; ++i) if( strcmp(u,G.vexs[i]) == 0) return i; return -1; } // 算法7.2 P162 // 采用数组(邻接矩阵)表示法,构造无向网G。 int CreateAN(MGraph *G) { int i,j,k,w,IncInfo; char s[MAX_INFO],*info; VertexType va,vb; printf("请输入无向网G的顶点数,边数,边是否含其它信息(是:1,否:0):(空格区分) "); scanf("%d%d%d%*c",&(*G).vexnum,&(*G).arcnum,&IncInfo); printf("请输入%d个顶点的值(<%d个字符):\n",(*G).vexnum,MAX_NAME); for(i=0;i<(*G).vexnum;++i) // 构造顶点向量 scanf("%s",(*G).vexs[i]); 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("请输入%d条边的顶点1 顶点2 权值(以空格作为间隔): \n",(*G).arcnum); for(k=0;k<(*G).arcnum;++k) { scanf("%s%s%d%*c",va,vb,&w); // %*c吃掉回车符 i=LocateVex(*G,va); j=LocateVex(*G,vb); (*G).arcs[i][j].adj=(*G).arcs[j][i].adj=w; // 无向 if(IncInfo) { printf("请输入该边的相关信息(<%d个字符): ",MAX_INFO); gets(s); w=strlen(s); if(w) { info=(char*)malloc((w+1)*sizeof(char)); strcpy(info,s); (*G).arcs[i][j].info=(*G).arcs[j][i].info=info; // 无向 } } } return 1; } // 求closedge.lowcost的最小正值 int minimum(minside SZ,MGraph G) { int i=0,min; while(!SZ[i].lowcost) i++; min=SZ[i].lowcost; // 第一个不为0的值 k=i; for(j=i+1;j<G.vexnum;j++) if(SZ[j].lowcost>0) if(min>SZ[j].lowcost) { min=SZ[j].lowcost; k=j; } return k; } // 算法7.9 P175 // 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边 void MiniSpanTree_PRIM(MGraph G,VertexType u) { int i,k; minside closedge; k=LocateVex(G,u); for(j=0;j<G.vexnum;++j) // 辅助数组初始化 { if(j!=k) { strcpy(closedge[j].adjvex,u); closedge[j].lowcost=G.arcs[k][j].adj; } } closedge[k].lowcost=0; // 初始,U={u} printf("最小代价生成树的各条边为:\n"); for(i=1;i<G.vexnum;++i) { // 选择其余G.vexnum-1个顶点 k=minimum(closedge,G); // 求出T的下一个结点:第K顶点 printf("(%s-%s)\n",closedge[k].adjvex,G.vexs[k]); // 输出生成树的边 closedge[k].lowcost=0; // 第K顶点并入U集 for(j=0;j<G.vexnum;++j) if(G.arcs[k][j].adj<closedge[j].lowcost) { // 新顶点并入U集后重新选择最小边 strcpy(closedge[j].adjvex,G.vexs[k]); closedge[j].lowcost=G.arcs[k][j].adj; } } } int main() { MGraph G; CreateAN(&G); MiniSpanTree_PRIM(G,G.vexs[0]); system("pause"); return 0; } /* 输出效果: 请输入无向网G的顶点数,否:0):(空格区分) 4 4 0 请输入4个顶点的值(<3个字符): a b c d 请输入4条边的顶点1 顶点2 权值(以空格作为间隔): a b 1 a c 2 b d 3 a d 1 最小代价生成树的各条边为: (a-b) (a-d) (a-c) 请按任意键继续. . . */