两种算法实现最小生成树.docx

上传人:b****4 文档编号:5474168 上传时间:2022-12-16 格式:DOCX 页数:13 大小:84.97KB
下载 相关 举报
两种算法实现最小生成树.docx_第1页
第1页 / 共13页
两种算法实现最小生成树.docx_第2页
第2页 / 共13页
两种算法实现最小生成树.docx_第3页
第3页 / 共13页
两种算法实现最小生成树.docx_第4页
第4页 / 共13页
两种算法实现最小生成树.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

两种算法实现最小生成树.docx

《两种算法实现最小生成树.docx》由会员分享,可在线阅读,更多相关《两种算法实现最小生成树.docx(13页珍藏版)》请在冰豆网上搜索。

两种算法实现最小生成树.docx

两种算法实现最小生成树

数据结构上机实验报告

题目:

两种算法实现最小生成树

学生姓名

学生学号

学院名称计算机学院

专业计算机科学与技术

时间2014.12.9

目录

第一章需求分析1

1.1原题表述1

1.2问题解决方案1

第二章概要设计2

2.1抽象数据类型2

2.2主要算法描述2

2.1.1Prim算法实现2

2.1.2Kruskal算法实现3

2.3主要算法分析3

第三章概要设计4

3.1程序代码4

3.1.1Prim算法实现4

3.1.2Kruskal算法实现6

第四章调试分析9

4.1出现的问题及解决方法9

第五章测试分析10

5.1测试样例10

 

第一章需求分析

1.1原题表述

某市为实现交通畅行,计划使全市中的任何两个村庄之间都实现公路互通,虽然不需要直接的公路相连,只要能够间接可达即可。

现在给出了任意两个城镇之间修建公路的费用列表,以及此两个城镇之间的道路是否修通的状态,要求编写程序求出任意两村庄都实现公路互通的最小成本。

输入参数:

测试输入包含若干测试用例。

每个测试用例的第1行给出村庄数目N(1

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且P(v,w),表示从v到w的弧,

谓词P(v,w)定义了弧的意义或信息}

基本操作:

CreatGraph(&G,V)

初始条件:

v是顶点数量

操作结果:

构造含有V个顶点的图G

Prim(G)

初始条件:

图G存在

操作结果:

找到图G中最小生成树

Kruskal(G)

初始条件:

图G存在

操作结果:

找到图G中最小生成树

}ADTGraph

2.2主要算法描述

2.1.1Prim算法实现

2.2.2Kruskal算法实现

2.3主要算法分析

Prim算法时间复杂度为O(n2),与图中顶点个数有关,而与边数无关。

Kruskal算法时间复杂度为O(eloge),与途中的边数有关,而与顶点数无关。

 

第三章详细设计

3.1程序代码

3.1.1Prim算法实现

#include

#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<=G.n;j++){

G.edges[i][j]=MAX;

}

}

for(inti=1;i<=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];//记录生成树顶点集合外各顶点距离集合内哪个顶点最近(即权值最小)

for(inti=1;i<=G.n;i++){//初始化lowcost[],vex[]

lowcost[i]=G.edges[1][i];

vex[i]=1;

}

vex[1]=-1;//加到生成树顶点集合

for(inti=2;i<=G.n;i++){//循环n-1次,加入n-1条边

intmin=MAX;

intk;//存放最小生成树结点的变量

for(intj=1;j<=G.n;j++){

if(vex[j]!

=-1&&lowcost[j]

min=lowcost[j];//求生成树外顶点到生成树内顶点具有最

k=j;//小权值的边,k是当前具最小权值的边

}

}

result=result+lowcost[k];//将最小权值记录

vex[k]=-1;//该边加入生成树标记

for(intj=1;j<=G.n;j++){//修改lowcost[],vex[]

if(vex[j]!

=-1&&G.edges[k][j]

lowcost[j]=G.edges[k][j];

vex[j]=k;

}

}

}

returnresult;

}

intmain()

{

while(true){

intv;

scanf("%d",&v);

if(v==0)break;

MGraphG;

CreatGraph(G,v);

intcost=Prim(G);

printf("%d\n",cost);

}

return0;

}

 

3.1.2Kruskal算法实现

#include

#defineNUM200//最大顶点个数

#defineEDGENUM20000//最大的边数

#defineMAX40000//最大值

//定义邻接矩阵的结构

typedefstruct

{

intedges[NUM][NUM];//邻接矩阵

intn;//顶点数

inte;//边数

}MGraph;

//定义边的结构

typedefstruct

{

intbegin;//边的起点

intend;//边的终点

intweight;//边的权值

}Edge;

//构造邻接矩阵,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<=G.n;j++){

G.edges[i][j]=MAX;

}

}

for(inti=1;i<=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;

}

}

//找顶点k的终点

intFind(intparent[],intk)

{

while(parent[k]>0){

k=parent[k];

}

returnk;

}

//Kruskal算法实现

intKruskal(MGraphG)

{

Edgeedge[EDGENUM];//图对应的所有边

intparent[EDGENUM];//用于记录顶点的终点

intk=1;//用于记录边的数量

for(inti=1;i<=G.n;i++){//构建边

for(intj=i+1;j<=G.n;j++){

edge[k].begin=i;

edge[k].end=j;

edge[k].weight=G.edges[i][j];

k++;

}

}

//根据边的权值大小对边数组进行从小到大排序

for(inti=1;i

for(intj=i+1;j

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数组

for(inti=1;i<=G.n;i++){

parent[i]=0;

}

intm,n;

intresult=0;//用于记录修路成本

for(inti=1;i<=G.e;i++){

//判断遍历的边是存在环

m=Find(parent,edge[i].begin);

n=Find(parent,edge[i].end);

if(m!

=n){

parent[n]=m;

result=result+edge[i].weight;

}

}

returnresult;

}

intmain()

{

while(true){

intv;

scanf("%d",&v);

if(v==0)break;

MGraphG;

CreatGraph(G,v);

intcost=Kruskal(G);

printf("%d\n",cost);

}

return0;

}

第四章调试分析

4.1出现的问题及解决方法

1.在调试过程中,为观察最短路径,输出了最短路径及权值:

 

2.在用Kruskal算法实现时,未考虑产生环的问题,而出现结果错误。

增加了查找边依附顶点的终点函数Find(),最后运行结果正确。

第五章测试分析

5.1测试样例

测试样例1:

Prim算法

图5-1

测试样例2:

Kruskal算法

图5-2

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1