石大《数据结构课程设计》.docx
《石大《数据结构课程设计》.docx》由会员分享,可在线阅读,更多相关《石大《数据结构课程设计》.docx(11页珍藏版)》请在冰豆网上搜索。
石大《数据结构课程设计》
中国石油大学(北京)
远程教育学院
《数据结构》课程设计报告
课程设计题目
知金教育北京数字化学习中心
学生姓名
李龙超
学号
101173
专业班级
2020年1月
题目要求:
设计一个稀疏矩阵计算器,实现两个稀疏矩阵的加法、减法、乘法以及矩阵的转置运算。
采用菜单为应用程序的界面,用户通过对菜单进行选择,分别实现矩阵的相加、相减、相乘以及矩阵转速运算。
1需求分析
1.至少包含10个城市;
2.城市数n由键盘录入;
3.城市坐标由随机函数产生小于100的整数;
4.输出生成树中各条边以及它们的权值;
5.利用克鲁斯卡尔算法求网的最小生成树。
6.实现并查集。
以此表示构造生成树过程中的连通分量。
7.以文本形式输出生成树中各条边以及他们的权值。
2概要设计
1、边集数组的类型定义:
typedefstruct
{
intx,y;
intw;
}edge;
x表示起点,y表示终点,w为权值。
2、并查集功能的实现由以下函数实现:
Make_Set(intx)初始化集合;
Find_Set(intx)查找x元素所在的集合,回溯时压缩路径;
Union(intx,inty,intw)合并x,y所在的集合。
克鲁斯卡尔算法的实现
该算法的实现位于主函数中:
qsort(e,n,sizeof(edge),cmp);//将边排序
printf("最小生成树的各条边及权值为:
\n");
for(i=0;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、设计中还包含以下函数:
/*比较函数,按权值(相同则按x坐标)非降序排序*/
intcmp(constvoid*a,constvoid*b)
{
if((*(edge*)a).w==(*(edge*)b).w)
{
return(*(edge*)a).x-(*(edge*)b).x;
}
return(*(edge*)a).w-(*(edge*)b).w;
}
5、主程序的流程图
3详细设计
#include
#include
#include"time.h"
#defineMAX435
/*定义边(x,y),权为w*/
typedefstruct
{
intx,y;
intw;
}edge;
edgee[MAX];
/*rank[x]表示x的秩*/
intrank[MAX];
/*father[x]表示x的父节点*/
intfather[MAX];
/*比较函数,按权值(相同则按x坐标)非降序排序*/
intcmp(constvoid*a,constvoid*b)
{
if((*(edge*)a).w==(*(edge*)b).w)
{
return(*(edge*)a).x-(*(edge*)b).x;
}
return(*(edge*)a).w-(*(edge*)b).w;
}
/*初始化集合*/
voidMake_Set(intx)
{
father[x]=x;
rank[x]=0;
}
/*查找x元素所在的集合,回溯时压缩路径*/
intFind_Set(intx)
{
while(father[x])
{
x=father[x];
}
returnx;
}
/*合并x,y所在的集合*/
voidUnion(intx,inty,intw)
{
if(x==y)return;
/*将秩较小的树连接到秩较大的树后*/
if(rank[x]>rank[y])
{
father[y]=x;
}
else
{
if(rank[x]==rank[y])
{
rank[y]++;
}
father[x]=y;
}
}
/*主函数*/
intmain()
{
printf("*最小生成树问题:
\n");
inti,n,h,k=0;
intx,y;
charchx,chy;
printf("\n人为输入权值请输入1,随机生成权值请输入0:
\n");
scanf("%d",&k);
if(k==1)
{
/*读取边的数目*/
printf("请输入边的条数(小于436):
\n");
scanf("%d",&n);
getchar();
/*读取边信息并初始化集合*/
printf("请输入边的信息(起点,终点,权值(<100))分别用空格隔开:
\n");
for(i=0;i{
scanf("%c%c%d",&chx,&chy,&e[i].w);
getchar();
e[i].x=chx-'A';
e[i].y=chy-'A';
Make_Set(i);
}
}
else{
printf("请输入顶点数(<=30):
\n");
scanf("%d",&h);
getchar();
srand((unsigned)time(NULL));
n=(h-1)*h/2;chx=49;chy=50;
for(i=0;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);
}
printf("随机生成的各条边及权值为:
\n");
for(i=0;i{
printf("%c-%c:
%d\n",e[i].x+'A',e[i].y+'A',e[i].w);
}
}
/*将边排序*/
qsort(e,n,sizeof(edge),cmp);
printf("最小生成树的各条边及权值为:
\n");
for(i=0;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);
}
}
return0;
}
1、边集数组的类型定义:
typedefstruct
{
intx,y;
intw;
}edge;
x表示起点,y表示终点,w为权值。
2、并查集功能的实现由以下函数实现:
Make_Set(intx)初始化集合;
Find_Set(intx)查找x元素所在的集合,回溯时压缩路径;
Union(intx,inty,intw)合并x,y所在的集合。
3、克鲁斯卡尔算法的实现
该算法的实现位于主函数中:
qsort(e,n,sizeof(edge),cmp);//将边排序
printf("最小生成树的各条边及权值为:
\n");
for(i=0;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坐标)非降序排序*/
intcmp(constvoid*a,constvoid*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(unsignedintseed);
使用随机数函数如下:
srand((unsigned)time(NULL));
for(i=0;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。
4程序测试
1、打开界面:
(1)人为输入权值,输入1,回车:
输入7,回车:
输入边的信息及结果如下:
(2)随机生成权值,输入0:
输入顶点数5,结果如下:
5感想与体会
通过本次课程设计,我学会了利用克鲁斯卡尔算法求最小生成树。
另外学会了利用随机函数产生随机数,以及课本没有提到的边集数组的定义和使用。