大数据结构课程设计-最小生成树
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《数据结构》期末课程设计
题目第8题:最小生成树问题学院计算机学院
专业
班别
学号
姓名陈聪
2015年7月6日
一、需求分析
1、问题描述
若要在n个城市之间建设通讯网络,只需要架设n-1条线路即可。如何以最低的经济代价建设这个通讯网,是一个网的最小生成树问题。
2、基本要求
(1)利用克鲁斯卡尔算法求网的最小生成树。
(2)实现并查集。以此表示构造生成树过程中的连通分量。
(3)以文本形式输出生成树中各条边以及他们的权值。
3、实现提示
通讯线路一旦建立,必然是双向的。因此,构造最小生成树的网一定是无向网。设图的顶点数不超过30个,并为简单起见,网中边的权值设成小于100的整数,可利用C语言提供的随机数函数产生。
图的存储结构的选取应和所作操作向适应。为了便于选择权值最小的边,此题的存储结构既不选用邻接矩阵的数组表示法,也不选用邻接表,而是以存储边(带权)的数组即边集数组表示图。
二、详细设计
根据课设题目要求,拟将整体程序分为三大模块,分别是:图的存储结构,并查集的实现,克鲁斯卡尔算法的实现。
1、边集数组的类型定义:
typedef struct
{
int x, y;
int w;
}edge;
x表示起点,y表示终点,w为权值。
2、并查集功能的实现由以下函数实现:
Make_Set(int x)初始化集合;
Find_Set(int x) 查找x元素所在的集合,回溯时压缩路径;
Union(int x, int y, int w)合并x,y所在的集合。
3、克鲁斯卡尔算法的实现
该算法的实现位于主函数中:
qsort(e, n, sizeof(edge), cmp); //将边排序
printf("最小生成树的各条边及权值为:\n");
for (i = 0; i < n; i++)
{
x = Find_Set(e[i].x);
y = Find_Set(e[i].y);
if (x != y )
{
printf("%c - %c : %d\n", e[i].x + 'A', e[i].y + 'A', e[i].w);
Union(x, y, e[i].w);
}
}
4、设计中还包含以下函数:
(1)/* 比较函数,按权值(相同则按x坐标)非降序排序*/ int cmp(const void *a, const void *b)
{
if ((*(edge *)a).w == (*(edge *)b).w)
{
return (*(edge *)a).x - (*(edge *)b).x;
}
return (*(edge *)a).w - (*(edge *)b).w;
}
(2)快排函数qsort,包含在stdlib.h头文件里
qsort(e, n, sizeof(edge), cmp);
(3)C语言提供的随机数函数srand( unsigned int seed );
使用随机数函数如下:
srand( (unsigned)time( NULL ) );
for( i = 0; i < n;i++ )
{
e[i].w=rand()%100+1;
e[i].x = chx - 'A';if(chy==h+48) chx++;
e[i].y = (chy++) - 'A';
if(chy==h+49) chy=chx+1;
Make_Set(i);
}
输出1~100之间的随机数,使用rand()%100+1。5 Array
三、调试分析
调试过程中遇到的问题:
随机产生权值时,通过边数不能确定起点和终点。解决:通过顶点数对所有边取随机数。
四、用户使用说明及测试结果
1、打开界面:
(1)人为输入权值,输入1,回车:
输入7,回车:
输入边的信息及结果如下:
(2)随机生成权值,输入0:
输入顶点数5,结果如下:
五、经验和体会
通过本次课程设计,我学会了利用克鲁斯卡尔算法求最小生成树。另外学会了利用随机函数产生随机数,以及课本没有提到的边集数组的定义和使用。
六、附录源代码
#include
#include
#include "time.h"
#define MAX 435
/* 定义边(x,y),权为w */
typedef struct
{
int x, y;
int w;
}edge;
edge e[MAX];
/* rank[x]表示x的秩*/
int rank[MAX];
/* father[x]表示x的父节点*/
int father[MAX];
/* 比较函数,按权值(相同则按x坐标)非降序排序*/ int cmp(const void *a, const void *b)
{
if ((*(edge *)a).w == (*(edge *)b).w)
{
return (*(edge *)a).x - (*(edge *)b).x;
}
return (*(edge *)a).w - (*(edge *)b).w;
}
/* 初始化集合*/
void Make_Set(int x)
{
father[x] = x;
rank[x] = 0;
}
/* 查找x元素所在的集合,回溯时压缩路径*/
int Find_Set(int x)
{
while(father[x])
{
x=father[x];
}
return x;
}
/* 合并x,y所在的集合*/
void Union(int x, int y, int w)
{
if (x == y) return;
/* 将秩较小的树连接到秩较大的树后*/
if (rank[x] > rank[y])
{
father[y] = x;
}
else