两种算法实现最小生成树Word格式.docx
- 文档编号:18461659
- 上传时间:2022-12-16
- 格式:DOCX
- 页数:13
- 大小:84.97KB
两种算法实现最小生成树Word格式.docx
《两种算法实现最小生成树Word格式.docx》由会员分享,可在线阅读,更多相关《两种算法实现最小生成树Word格式.docx(13页珍藏版)》请在冰豆网上搜索。
第五章测试分析10
5.1测试样例10
第一章需求分析
1.1原题表述
某市为实现交通畅行,计划使全市中的任何两个村庄之间都实现公路互通,虽然不需要直接的公路相连,只要能够间接可达即可。
现在给出了任意两个城镇之间修建公路的费用列表,以及此两个城镇之间的道路是否修通的状态,要求编写程序求出任意两村庄都实现公路互通的最小成本。
输入参数:
测试输入包含若干测试用例。
每个测试用例的第1行给出村庄数目N(1<
N<
100);
随后的N(N-1)/2行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:
1表示已建,0表示未建。
当N为0时输入结束。
输出参数:
每个测试用例占输出的一行,输出实现后所需的最小成本值
1.2问题解决方案
第一种方案:
使用Prim算法
首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出与最小生成树中各结点权重最小边,并加入到最小生成树中。
加入之后如果产生回路则跳过这条边,选择下一个结点。
当所有结点都加入到最小生成树中之后,就找出了连通图中的最小生成树了。
第二种方案:
使用kruskal算法
算法过程:
1.将图各边按照权值进行排序2.将图遍历一次,找出权值最小的边,(条件:
此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。
不符合条件则继续遍历图,寻找下一个最小权值的边。
3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。
得到的就是此图的最小生成树。
第二章概要设计
2.1抽象数据类型
ADTGraph{
数据对象V:
V是具有相同特性的数据元素的和,称为顶点级。
数据关系R:
R={VR}
VR={<
v,w>
|v,w
V且P(v,w),<
表示从v到w的弧,
谓词P(v,w)定义了弧<
的意义或信息}
基本操作:
CreatGraph(&
G,V)
初始条件:
v是顶点数量
操作结果:
构造含有V个顶点的图G
Prim(G)
图G存在
找到图G中最小生成树
Kruskal(G)
}ADTGraph
2.2主要算法描述
2.1.1Prim算法实现
2.2.2Kruskal算法实现
2.3主要算法分析
Prim算法时间复杂度为O(n2),与图中顶点个数有关,而与边数无关。
Kruskal算法时间复杂度为O(eloge),与途中的边数有关,而与顶点数无关。
第三章详细设计
3.1程序代码
3.1.1Prim算法实现
#include<
stdio.h>
#defineNUM200//最大顶点数
#defineMAX40000//最大值
//定义邻接矩阵的结构
typedefstruct
{
intedges[NUM][NUM];
//邻接矩阵
intn;
//顶点数
inte;
//边数
}MGraph;
//构造邻接矩阵,v表示顶点数
voidCreatGraph(MGraph&
G,intv)
G.n=v;
G.e=v*(v-1)/2;
for(inti=1;
i<
=G.n;
i++){//初始化邻接矩阵
for(intj=1;
j<
j++){
G.edges[i][j]=MAX;
}
=G.e;
i++){//构造邻接矩阵
//v1,v2一条路连接的两村庄,cost修路费用,build修建状态
intv1,v2,cost,build;
scanf("
%d%d%d%d"
&
v1,&
v2,&
cost,&
build);
if(build==1)
cost=0;
G.edges[v1][v2]=cost;
G.edges[v2][v1]=cost;
}
intPrim(MGraphG)
intresult=0;
//用于记录修路成本
intlowcost[NUM];
//存放生成树顶点集合内顶点到生成树外各顶点的各边上的当前最小权值
intvex[NUM];
//记录生成树顶点集合外各顶点距离集合内哪个顶点最近(即权值最小)
i++){//初始化lowcost[],vex[]
lowcost[i]=G.edges[1][i];
vex[i]=1;
vex[1]=-1;
//加到生成树顶点集合
for(inti=2;
i++){//循环n-1次,加入n-1条边
intmin=MAX;
intk;
//存放最小生成树结点的变量
if(vex[j]!
=-1&
&
lowcost[j]<
min){
min=lowcost[j];
//求生成树外顶点到生成树内顶点具有最
k=j;
//小权值的边,k是当前具最小权值的边
result=result+lowcost[k];
//将最小权值记录
vex[k]=-1;
//该边加入生成树标记
j++){//修改lowcost[],vex[]
G.edges[k][j]<
lowcost[j]){
lowcost[j]=G.edges[k][j];
vex[j]=k;
returnresult;
intmain()
while(true){
intv;
%d"
v);
if(v==0)break;
MGraphG;
CreatGraph(G,v);
intcost=Prim(G);
printf("
%d\n"
cost);
return0;
3.1.2Kruskal算法实现
#defineNUM200//最大顶点个数
#defineEDGENUM20000//最大的边数
//定义边的结构
intbegin;
//边的起点
intend;
//边的终点
intweight;
//边的权值
}Edge;
//找顶点k的终点
intFind(intparent[],intk)
while(parent[k]>
0){
k=parent[k];
returnk;
//Kruskal算法实现
intKruskal(MGraphG)
Edgeedge[EDGENUM];
//图对应的所有边
intparent[EDGENUM];
//用于记录顶点的终点
intk=1;
//用于记录边的数量
i++){//构建边
for(intj=i+1;
edge[k].begin=i;
edge[k].end=j;
edge[k].weight=G.edges[i][j];
k++;
//根据边的权值大小对边数组进行从小到大排序
k;
i++){
if(edge[i].weight>
edge[j].weight){
inttemp;
temp=edge[i].begin;
edge[i].begin=edge[j].begin;
edge[j].begin=temp;
temp=edge[i].end;
edge[i].end=edge[j].end;
edge[j].end=temp;
temp=edge[i].weight;
edge[i].weight=edge[j].weight;
edge[j].weight=temp;
//初始化parent数组
parent[i]=0;
intm,n;
//判断遍历的边是存在环
m=Find(parent,edge[i].begin);
n=Find(parent,edge[i].end);
if(m!
=n){
parent[n]=m;
result=result+edge[i].weight;
intcost=Kruskal(G);
第四章调试分析
4.1出现的问题及解决方法
1.在调试过程中,为观察最短路径,输出了最短路径及权值:
2.在用Kruskal算法实现时,未考虑产生环的问题,而出现结果错误。
增加了查找边依附顶点的终点函数Find(),最后运行结果正确。
第五章测试分析
5.1测试样例
测试样例1:
Prim算法
图5-1
测试样例2:
Kruskal算法
图5-2
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算法 实现 最小 生成