数据结构总结13——图4——图的最小生成树(普里姆算法) by DexterYan

    xiaoxiao2024-11-20  3

    一、基础知识

    二、代码要求

    邻接矩阵、邻接表中任选一种作为图的存储结构, 采用普里姆(Prim)算法,、 实现按逐个将定点连通的方式来构造最小生成树(2学时)

    三、算法思路分析

    基本思想: 假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。 算法从U={u0}(u0∈V)、TE ={}开始。 重复执行下列操作: 在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中, 同时v0并入U,直到V=U为止。此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。

    U和V-U是两个定义的顶点集合,初始化U为空集,则V-U就是剩下的顶点数,

    最小生成树MST是图论中的基本算法。一般使用Prim算法或者Kruskal算法解决。 这两类算法都是贪心算法, Prim算法是基于点的,而Kruskal算法是基于边的。

    四、算法反思

    五、代码实现

    #include<stdio.h> #include<stdlib.h> #define MaxVertexNum 100 typedef char VertexType; typedef int EdgeType; typedef struct { int vexs[MaxVertexNum];//顶点表 EdgeType edges[MaxVertexNum][MaxVertexNum];//边表,邻接矩阵 int n,e;//顶点数和边数 }MGraph;//以邻接矩阵存储图类型 struct node { int adjvex; int lowcost; //存储该边上的权 }closedge[MaxVertexNum];//一维辅助数组,记录从U到U-V具有最小权值的边 (U是生成树顶点集合) int visited[MaxVertexNum]; int CreateMGraph(MGraph *G)//建立图的邻接矩阵 { int i, j, k, weight; printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n"); scanf("%d,%d",&(G->n),&(G->e));//输入顶点数和边数 /*这G->n不加括号括起来有无影响?*/ printf("请输入顶点信息(输入格式为:<回车>顶点号):\n"); for(i=0; i<G->n; i++) { scanf("\n%d",&(G->vexs[i]));//输入顶点信息,顶点集 } for(i=0; i<G->n; i++) { for(j=0; j<G->n; j++) { G->edges[i][j]=9999;//初始化邻接矩阵 } } printf("请输入每条边对应的两个顶点的序号和对应的权值(输入格式为:i,j,weight):\n"); for(k=0; k<G->e; k++) { scanf("%d,%d,%d",&i,&j,&weight); G->edges[i][j]=weight;//若此处加入G->deges[j][i]=1,则为无向图的邻接矩阵存储建立 G->edges[j][i]=weight; } /*用来显示邻接矩阵,检测创建是否正确 for(i=0; i<G->n; i++) { for(j=0; j<G->n; j++) { printf("(%d)",G->edges[i][j]); } printf("\n"); } */ } void Prim(MGraph G,int v)//v为起始顶点号 {/*G位图的邻接矩阵存储结构,v是第一个额进入集合U中的顶点的序号*/ int k,j,i,minCost; struct node closedge[MaxVertexNum]; closedge[v].lowcost=0; for(j=0; j<G.n; j++)//初始化closedge数组,定义的起始点在closedge中的lowcost为0 if(j!=v) { closedge[j].adjvex=v;//初始化数组的第一个顶点加入 closedge[j].lowcost=G.edges[v][j]; } for(i=1; i<G.n; i++)//依次将顶点加入到集合U中 { for(j=0; j<G.n; j++) { if(closedge[j].lowcost!=0)//定位第一个没有加入到集合U中的顶点 { k=j; break;// } } minCost=closedge[k].lowcost;//这步和下边的for循环都是在定位V-U集合中lowcost值最小的顶点 for(j=0; j<G.n; j++)//把第一个不为上一个检测的最小值给mincost {//遍历,定位最小的lowcost if(closedge[j].lowcost<minCost&&closedge[j].lowcost!=0) { minCost=closedge[j].lowcost; k=j; } } printf("(%d,%d)\n",closedge[k].adjvex,G.vexs[k]);//输出新加入到树上的边 closedge[k].lowcost=0; //将该顶点加入到集合U for(j=0; j<G.n; j++) //更新closedge数组的内容 { if(G.edges[k][j]<closedge[j].lowcost)//如果以上一个刚加入到集合U的顶点,其邻边权值有小于原closedge的信息的 {//则更新 closedge[j].adjvex=G.vexs[k]; closedge[j].lowcost=G.edges[k][j]; } } } } int main() { MGraph x; int start; CreateMGraph(&x); // printf("请设置起始顶点:"); //scanf("请设置起始顶点:%d\n",&start); Prim(x,0); return 0; }

    六、代码反思

    脑残bug:第一版由于桉书抄,邻接矩阵顶点为char类型,closedge为int类型,发生了自动类型转换,0为NULL,导致没有值。

    转载:自动类型转换和强制类型转换 (原文链接:https://blog.csdn.net/weixin_41588502/article/details/80549827) 1.当类型转换出现在表达式中,无论是unsigned还是signed的char和short都会被自动转换为int,如有必要会被转换为unsigned int (如果short和int的大小相同,unsignedshort就比int大。这种情况下unsigned short就会转化成unsigned int)。 2.当作为函数参数传递时,char和short被转换成int,float被转换成double。

    以上两种情况都是数据类型升级

    二.强制类型转换 举例说明: Size = (int)1.6 + (int)2.6; Size得3。使用了强制性转换将1.6和2.6转换为了整数类型,分别为1和2。 因此其用法就是在你需要转换类型的数据左边加圆括号,其里面的数据类型就是你想转换的数据类型。

    最新回复(0)