实验5 最小生成树算法的设计与实现(报告)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验5 最小生成树算法的设计与实现

一、实验目的

1、根据算法设计需要, 掌握连通图的灵活表示方法;

2、掌握最小生成树算法,如Prim、Kruskal算法;

3、基本掌握贪心算法的一般设计方法;

4、进一步掌握集合的表示与操作算法的应用。

二、实验内容

1、认真阅读算法设计教材和数据结构教材内容, 熟习连通图的不同表示方法和最小生成树算法;

2、设计Kruskal算法实验程序。

有n个城市可以用(n-1)条路将它们连通,求最小总路程的和。

设计测试问题,修改并调试程序, 输出最小生成树的各条边, 直至正确为止。

三、Kruskal算法的原理方法

边权排序:

1 3 1

4 6 2

3 6 4

1 4 5

2 3 5

3 4 5

2 5 6

1 2 6

3 5 6

5 6 6

1. 初始化时:属于最小生成树的顶点U={}

不属于最小生成树的顶点V={1,2,3,4,5,6}

2. 根据边权排序,选出还没有连接并且权最小的边(1 3 1),属于最小生成树

的顶点U={1,3},不属于最小生成树的顶点V={2,4,5,6}

3. 根据边权排序,选出还没有连接并且权最小的边(4 6 2),属于最小生成树的顶点U={{1,3},{4,6}}(还没有合在一起,有两颗子树),不属于最小生成树的顶点V={2,5}

4. 根据边权排序,选出还没有连接并且权最小的边(3 6 4),属于最小生成树的顶点U={1,3,4,6}(合在一起),不属于最小生成树的顶点V={2,5}

5. 根据边权排序,选出还没有连接并且权最小的边(3 6 4),属于最小生成树的顶点U={1,2,3,4,6},,不属于最小生成树的顶点V={5}

6. 根据边权排序,选出还没有连接并且权最小的边(3 6 4),属于最小生成树的顶点U={1,2,3,4,5,6}此时,最小生成树已完成

四、实验程序的功能模块

功能模块:

bool cmp(Edge a,Edge b);//定义比较方法

int getfa(int x);//在并查集森林中找到x的祖先

int same(int x,int y);//判断祖先是否是同一个,即是否联通void merge(int x,int y); //合并子树,即联通两子树

sort(e+1,e+m+1,cmp); //对边按边权进行升序排序

详细代码:

#include

#include

#include

#include

#define MAXN_E 100000

#define MAXN_V 100000

using namespace std;

struct Edge{

int fm,to,dist; //边的起始顶点,边的到达顶点,边权}e[MAXN_E];

int fa[MAXN_V],n,m; //顶点数组,顶点总数,边总数

//定义比较,只是边权比较

bool cmp(Edge a,Edge b){

return a.dist < b.dist;

}

//查找x的祖先

int getfa(int x){//getfa是在并查集森林中找到x的祖先if(fa[x]==x) return fa[x];

else return fa[x] = getfa(fa[x]);

}

//判断祖先是否是同一个,即是否联通

int same(int x,int y){

return getfa(x)==getfa(y);

}

//合并两棵树

void merge(int x,int y){

int fax=getfa(x),fay=getfa(y);

fa[fax]=fay;

}

int main(){

int i;

cout<<"请输入顶点数目和边数目:"<

cin>>n>>m;//n为点数,m为边数

//输出顶点信息

cout<<"各个顶点值依次为:"<

for(i=0;i

{

fa[i]=i;

if(i!=0)

cout<

}

cout<

cout<<"请输入边的信息(例子:1 4 5 从顶点1到顶点4的边权为5)"<< endl;

for(i=1;i<=m;i++)

cin>>e[i].fm>>e[i].to>>e[i].dist;//用边集数组存放边,方便排序和调用sort(e+1,e+m+1,cmp); //对边按边权进行升序排序

int rst=n,ans=0;//rst表示目前的点共存在于多少个集合中,初始情况是每个点都在不同的集合中

for(i=1;i<=m && rst>1;i++)

{

int x=e[i].fm,y=e[i].to;

if(same(x,y)) continue;//same函数是查询两个点是否在同一集合中

else

{

merge(x,y);//merge函数用来将两个点合并到同一集合中

rst--;//每次将两个不同集合中的点合并,都将使rst值减1

ans+=e[i].dist;//这条边是最小生成树中的边,将答案加上边权}

}

cout<

return 0;

}

五、测试数据和相应的最小生成树

Input:

6 10

1 2 6

1 3 1

1 4 5

2 3 5

2 5 6

3 4 5

3 5 6

相关文档
最新文档