1、 要在 n 个城市间建立交通网,要考虑的问题如何在保证 n 点连通的前题下最节省经费?邻接表的存储结构MST性质: 假设G=(V,E)是一个连通网,U是顶点集V的一个非空真子集,若(u,v)是满足u U,v V-U的边(称这种边为两栖边)且(u,v)在所有的两栖边中具有最小的权值(此时,称(u,v)为最小两栖边),则必存在一棵包含边(u,v)的最小生成树。求MST的一般算法描述 求MST的一般算法可描述为:针对图G,从空树T开始,往集合T中逐条选择并加入n-1条安全边(u,v),最终生成一棵含n-1条边的MST。 当一条边(u,v)加入T时,必须保证T(u,v)仍是MST的子集,我们将这样的边
2、称为T的安全边。(Prim)算法和(Kruskal)算法是两个利用MST性质构造最小生成树的算法。最小生成树的普里姆算法:普里姆算法的基本思想:从连通网络 G = V, E 中的某一顶点 u0 出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。 以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把它的顶点加入到集合U中。如此继续下去,直到网络中的所有顶点都加入到生成树顶点集合U中为止。Prim算法的基本步骤如下:(1)初始化:U=u0,TREE=;(2)如果U=V(G),则输出最小生成树T,并结束算法;(3)在所有两栖
3、边中找一条权最小的边(u,v)(若候选两栖边中的最小边不止一条,可任选其中的一条),将边(u,v)加入到边集TREE中,并将顶点v并入集合U中。(4)由于新顶点的加入,U的状态发生变化,需要对U与V-U之间的两栖边进行调整。(5)转步骤(2)普里姆算法构造最小生成树的过程 Prim算法实现:1、连通图用邻接矩阵表示: int i,j,k,w; Vertex va,vb; printf(输入顶点数和边数n); scanf(%d%d,&G.vexnum,&G.arcnum);输入%d个顶点的值(%d个字符,以空格间隔):n,G.vexnum,maxname); for(i=0;iG.vexnum;
4、+i) scanf(%s,G.vexsi); for(j=0;j+j) G.arcsij=0x7fffffff; printf(输入%d条边的顶点1 顶点2 权值:,G.arcnum); for(k=0;kG.arcnum;+k) scanf(%s%s%d%*c,va,vb,&w); i=locate(G,va); j=locate(G,vb); G.arcsij=G.arcsji=w; 2、 生成树 int i,j,k; minside closedge; k=locate(G,u); for(j=0; strcpy(closedgej.adjvex,u);/将u赋给closedgej.ad
5、jvex closedgej.lowcost=G.arcskj; closedgek.lowcost=0;最小代价生成树的各条边为: for(i=1; k=minimum(closedge,G);(%s-%s)n,closedgek.adjvex,G.vexsk); closedgek.lowcost=0; if(G.arcskj0&minminaj.lowcost) min=minaj.lowcost; k=j; return k;为实现prim算法需附设一个辅助数组closedge,以记录从U到V-U具有最小代价的边。对于每个顶点Vi属于V-U,在辅助数组中存在一个相应分量closedge
6、i-1,它包括两个域,其中lowcost存储该边上的权。typedef structVertex adjvex;/当前点int lowcost;/权值minsidemaxvertexnumber;程序运行结果截图:最小生成树的克鲁斯卡尔算法:Kruskal算法基本思想:为使生成树上边的权值之和最小,显然,其中每一条边的权值应该尽可能地小。克鲁斯卡尔算法的做法就是:先构造一个只含n个顶点的子图SG,然后从权值最小的边开始,若它的添加不使SG中产生回路,则在SG上加上这条边,如此重复,直至加上n-1条边为止。克鲁斯卡尔算法构造最小生成树的过程克鲁斯卡尔算法的实现:(1)初始化;(2)将所有的边按权
7、值大小排序;(3)遍历具有相互间具有共同顶点的边,若一条边的两顶点在同一连同分量上,则舍弃(4)如果具有n-1条边,则输出最小生成树,并结束算法。用冒泡法对所有边的权值进行排序:void sortorder(edge &minedge) int i,j,temp;edgenum-1;i+)edgenum-1-i; if(minedgej.costminedgej+1.cost) temp=minedgej.adjvex; minedgej.adjvex=minedgej+1.adjvex; minedgej+1.adjvex=temp; temp=minedgej.endvex; minedg
8、ej.endvex=minedgej+1.endvex; minedgej+1.endvex=temp; temp=minedgej.cost; minedgej.cost=minedgej+1.cost; minedgej+1.cost=temp;寻找最小生成树的路径:void mintree(vex &minvex,edge &minedge) int i,j,count=0,k=0;edgenum; if(k=vexnum-1) break; if(minvexminedgei.adjvex.sign=minvexminedgei.endvex.sign) continue; else
9、minedgei.sign=1;/把已经包含在最小生成树里的节点序号记为1 for(j=0;vexnum; if(minvexj.sign=minvexminedgei.endvex.sign) minvexj.sign=minvexminedgei.adjvex.sign; k+;输出最小生成树的各边:void print(vex minvex,edge minedge)int i;最小生成树如下nif(minedgei.sign=1) printf(%c%c %dn,minvexminedgei.adjvex.vexname,minvexminedgei.endvex.vexname,mi
10、nedgei.cost);无向图的邻接表 对于图G中的每个顶点vi,该方法把所有邻接于vi的顶点vj链成一个带头结点的单链表,这个单链表就称为顶点vi的邻接表。单链表中的每个结点至少包含两个域,一个为邻接点域(adjvex),它指示与顶点vi邻接的顶点在图中的位序,另一个为链域(next),它指示与顶点vi邻接的下一个结点。 为了便于随机访问任一顶点的邻接表,可将所有头结点顺序存储在一个向量中就构成了图的邻接表存储。最后将图的顶点数及边数等信息与邻接表放在一起来描述图的存储结构。#include stdlib.h#define m 20 /*预定义图的最大顶点数*/typedef char d
11、atatype; /*顶点信息数据类型*/typedef struct node /*边表结点*/ int adjvex; /*邻接点*/ struct node *next;edgenode;typedef struct vnode /*头结点类型*/ datatype vertex; /*顶点信息*/ edgenode *firstedge; /*邻接链表头指针*/vertexnode;typedef struct /*邻接表类型*/ vertexnode adjlist m; /*存放头结点的顺序表*/ int n,e; /*图的顶点数与边数*/adjgraph;void createa
12、djgraph(adjgraph *g) int i,j,k; edgenode *s;Please input n and e:g-n,&e); /*输入顶点数与边数*/ getchar();Please input %d vertex:,g-n);for(i=0;n; scanf(“%c”,&adjlisti.vertex); /*读入顶点信息*/ g-adjlisti.firstedge=NULL; /*边表置为空表*/Please input %d edges: for(k=0;e;k+) /*循环e次建立边表*/ scanf(i,&j); /*输入无序对(i,j)*/ s=(edge
13、node *)malloc(sizeof(edgenode); s-adjvex=j; /*邻接点序号为j*/next=g-adjlisti.firstedge;adjlisti.firstedge=s;adjvex=i; /*邻接点序号为i*/adjlistj.firstedge;adjlistj.firstedge=s; /*将新结点*s插入顶点vj的边表头部*/参考文献 1 孟彩霞. 计算机软件基础M. 陕西:西安电子科技大学出版社, 2003.2 严蔚敏, 吴伟民. 数据结构M. 北京:清华大学出版社, 2005.3 谭浩强. C程序设计(第二版)M. 北京:清华大学出版社, 1999.4 CSDN网,5 编程中国,6 编程入门网,
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1