数据结构课程设计.docx
- 文档编号:6904916
- 上传时间:2023-01-12
- 格式:DOCX
- 页数:14
- 大小:33.41KB
数据结构课程设计.docx
《数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计.docx(14页珍藏版)》请在冰豆网上搜索。
数据结构课程设计
华南农业大学信息学院
课程设计实验
学院
班级
学号
姓名
实
验
题
目
■设计性□综合性
自
我
评
价
在本次并查集的程序设计中,由于自己之前没有接触过,而且由于自己上学期数据结构的基础没学好,所以在自学并查集的过程中遇到了很大的困难。
所以在代码实现方面也相对简陋。
但是自己还是查阅了很多资料,也请教了很多同学,最终才勉强算解决了。
但是,从这里我得到的启发就是,只有丰富自身的知识以及思想高度才能做出更好的设计产品来。
教
师
评
语
能够实现实验要求的功能□全部□部分
算法有新意□有□一般
程序运行通过□全部□部分
算法注释说明□完善□仅有功能说明
接口参数说明□有□无
按期上交文档资料及源程序□所有□部分
独立完成实验□能□不能
体现团队合作精神。
□能够□不能
成绩
一、分析题目要求
1、在这个课程设计中,我做的是并查集。
主要实现以下的功能:
1)初始化
2)合并结合
3)查找节点所在集合
4)相关应用
初始化:
把每个点所在集合初始化为其自身。
通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式时间复杂度均为O(N)。
查找:
查找元素所在的集合,即根节点。
合并:
将两个元素所在的集合合并为一个集合。
通常来说,合并之前,应先判断两个元素是否属于同一集合,这可用上面的“查找”操作实现。
为了在这个程序实现中更好地表现出相关功能,我用了一个具体的例子,也即是判断多个城市之间的并查集,并求出不同城市的距离长短。
2、各个函数命名,包含的参数,返回值类型
intmenu()//函数主菜单
voidxin_input()//第二级菜单
boolcmp(nodep1,nodep2)
//并查集
voidset(intx)//初始化
intfind(intx)//寻找数据的共同祖先
voidUnion(intx,inty)//合并函数
//算法
voidKruskal()//Kruskal算法
intprim()//prim算法
voidShortestPath_DIJ(intx,inty)//Dijkstra算法
voidShortestPath_FLOYD()//Floyd算法
voidshuru()//接收函数(接收输入的数据)
voidchaxun()//查询函数
//功能函数
voidchaxun_func()
voidjudge()
intmain()//主函数
3、程序的运行
二、解题思路
1、单链表实现
一个节点对应一座城市,在同一个集合中的节点串成一条链表就得到了单链表的实现。
在集合中我们以单链表的第一个节点作为集合的代表元。
于是每个节点x(x也是城市的编号)应包含这些信息:
指向代表元即表首的指针head[x],指向表尾的指针tail[x],下一个节点的指针next[x]。
2、两大优化
第一个优化是启发式合并。
在优化单链表时,我们将较短的表链到较长的表尾,在这里我们可以用同样的方法,将深度较小的树指到深度较大的树的根上。
这样可以防止树的退化,最坏情况不会出现。
Find-Set(x)的时间复杂度为O(logN),PROBLEM-Relations时间复杂度为O(N+logN(M+Q))。
SUB-Link(a,b)作相应改动
第二个优化是路径压缩。
它非常简单而有效。
如图所示,在Find-Set
(1)时,我们“顺便”将节点1,2,3的父节点全改为节点4,以后再调用-Find-Set
(1)时就只需O
(1)的时间。
三、调试分析
由于此程序实现的功能较为简单,故在调试过程中也没遇到很大的问题。
主要的问题在于着手写代码的时候,由于不熟悉及很多算法未接触过,故陷入了无从下手的境地。
但最后通过搜索大量的资料终于解决。
期间用到的测试数据是多组邻接矩阵,没有发现bug;对于算法的不足之处,主要是时间复杂度过大,代码未能很好优化,另外对于改进的设想,也就是前面提到的两大优化,但由于自己未能实现,故只好作罢了。
所以,此次最大的感受就是自己的知识基础很薄弱,而且对于很多思维性和逻辑性要求很高的东西自己难以理解。
所以自己深知要加强这方面的锻炼。
更为自己过去一学期没能好好掌握的知识而感到痛心,有机会一定要补回来吧。
四、附录
带注释的源程序。
#include
#include
#include
#include
#include
usingnamespacestd;
intn=0;
inta[100][100];
intmenu()
{
intm;
printf("并查集\n");
printf("________________________________\n\n");
printf("1输入城市之间的信息\n");
printf("2判断是否能构成一个并查集\n");
printf("3查询信息\n");
printf("4退出\n");
printf("________________________________\n\n");
printf("请输入所选功能1--4\n");
scanf("%d",&m);
returnm;
}
voidxin_input()
{
system("cls");
printf("________________________________\n\n");
printf("1遍历所有城市的并查集\n");
printf("2查询两个城市之间的距离\n");
printf("3退出\n");
printf("________________________________\n\n");
}
//以下为克鲁斯卡尔算法
typedefstructnode//构造一个结构体,两个城市可以看成起点和终点,之间的路道可以看成一个边
{
intst;//起点
inted;//终点
intdis;//距离
}node;
nodep[1000];
intpre[1000],rank[1000];
boolcmp(nodep1,nodep2)
{
returnp1.dis } //下面三个函数是并查集,其作用是检验当一条边添加进去,是否会产生回路 voidset(intx) { pre[x]=x;//初始化 rank[x]=0; } intfind(intx)//找到这个点的祖先 { if(x! =pre[x]) pre[x]=find(pre[x]); returnpre[x]; } voidUnion(intx,inty)//将这两个添加到一个集合里去 { x=find(x); y=find(y); if(rank[x]>=rank[y]) { pre[y]=x; rank[x]++; } else pre[y]=x; } voidKruskal()// { intans=0,i,j,k=0; for(i=1;i<=n;i++) set(i); for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) { p[++k].st=i; p[k].ed=j; p[k].dis=a[i][j];//先把所有城市之间的路段看成一个边 } sort(p+1,p+k+1,cmp);//把所有的边按从小到大进行排序 intcount=0; for(i=1;i<=k;i++) { if(find(p[i].st)! =find(p[i].ed))//如果这两点连接在一起不构成一个回路,则执行下面操作 { printf("第%d条路段为: %d--%d,权值为%d\n",++count,p[i].st,p[i].ed,p[i].dis);//将这条边的起点、终点打印出来 ans+=p[i].dis;//说明这条路段要用 Union(p[i].st,p[i].ed); } } printf("遍历所有城市的最短路程为: %d\n",ans);//最短遍历的路程 //printf("________________________________\n"); } //普里姆算法 intprim() { intclose[100],low[100],i,j,ans=0;//close[j]表示离j最近的顶点,low[j]表示离j最短的距离 booluse[100]; use[1]=1; for(i=2;i<=n;i++) { low[i]=a[1][i];//初始化 close[i]=1; use[i]=0; } for(i=1;i { intmin=100000000,k=0; for(j=2;j<=n;j++) { if(use[j]==0&&min>low[j])//找到最小的low[]值,并记录 { min=low[j]; k=j; } } //printf("%d%d\n",close[k],k); for(j=2;j<=n;j++) { if(use[j]==0&&low[j]>a[k][j]) { low[j]=a[k][j];//修改low[]值和close[]值 close[j]=k; } } ans+=a[close[k]][k]; } returnans; } //求最短路径-单源点到其余点的最短路径(Dijkstra算法) voidShortestPath_DIJ(intx,inty)//X指单源点,y指目标点 { inti,d[100],j; booluse[100]; for(i=1;i<=n;i++) { use[i]=0;//初始化 d[i]=a[x][i]; } use[x]=1;//这个点肯定用过 d[x]=0; for(i=1;i { intmin=100000000,v; for(j=1;j<=n;j++) { if(use[j]==0&&min>d[j])//找出最短距离的 { min=d[j]; v=j; } } use[v]=1; for(j=1;j<=n;j++) { if(use[j]==0&&d[j]>min+a[v][j])//修改d[]的值 { d[j]=min+a[v][j]; } } } printf("%d城市到城市%d的最短距离为: %d\n",x,y,d[y]); } //求每一对顶点之间的最短路径(Floyd算法) intb[100][100]; voidShortestPath_FLOYD()//这个算法耗时多(n^3),不过容易理解 { inti,j,k; for(i=1;i<=n;i++) for(j=1;j<=n;j++) b[i][j]=a[i][j];//先b[][]进行保存,避免a[][]的值发生变化 for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(b[i][j]>b[i][k]+b[k][j]) b[i][j]=b[i][k]+b[k][j]; while (1) { system("cls"); intst,ed; printf("请输入两个城市的编号: \n");//对此进行多次操作 scanf("%d%d",&st,&ed); printf("%d城市到%d城市的最短距离为: %d\n",st,ed,b[st][ed]); //printf("________________________________\n"); charstr[100]; printf("是否要继续? yesorno\n"); scanf("%s",str); if(strcmp(str,"no")==0) {//printf("________________________________\n"); break; } } } voidshuru()//输入城市信息 { inti,j; if(n! =0) { charstr[100]; printf("是否要确定输入新的城市之间的信息? yesorno? \n"); scanf("%s",str); if(strcmp(str,"no")==0) { return; } } printf("请输入城市的个数: \n"); scanf("%d",&n); printf("输入%d个城市的邻接矩阵: \n",n); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) scanf("%d",&a[i][j]); } //printf("________________________________\n"); } voidchaxun()//一个查徇两个城市最短径的操作 { while (1) { system("cls"); intt1,t2; printf("输入第一个城市的编号: \n"); scanf("%d",&t1); printf("输入第二个城市的编号: \n"); scanf("%d",&t2); ShortestPath_DIJ(t1,t2);//调用 charstr[100]; printf("是否要继续? yesorno\n"); scanf("%s",str); if(strcmp(str,"no")==0) { //printf("________________________________\n"); break; } } } voidchaxun_func() { if(n==0) { printf("这里没有城市之间的信息\n"); return; } xin_input(); printf("请选择以上功能: 1-3\n"); intm1; scanf("%d",&m1); printf("\n"); if(m1==1) Kruskal(); elseif(m1==2) { system("cls"); chaxun(); } //else //break; } voidjudge() { system("cls"); intans; ans=prim(); if(ans>=100000000) printf("不能构成并查集\n"); else printf("\n\n\n\n能构成并查集! \n\n\n\n\n"); } intmain() { while (1) { switch(menu()) { case1: shuru();break;system("cls"); case2: judge();break;system("cls"); case3: chaxun_func();break;system("cls"); case4: gotoloop; } } loop: ;system("cls"); return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计