数据结构课程设计报告3.doc

上传人:仙人指路1688 文档编号:2396821 上传时间:2023-02-17 格式:DOC 页数:22 大小:145KB
返回 下载 相关 举报
数据结构课程设计报告3.doc_第1页
第1页 / 共22页
数据结构课程设计报告3.doc_第2页
第2页 / 共22页
数据结构课程设计报告3.doc_第3页
第3页 / 共22页
数据结构课程设计报告3.doc_第4页
第4页 / 共22页
数据结构课程设计报告3.doc_第5页
第5页 / 共22页
点击查看更多>>
资源描述

《数据结构课程设计报告3.doc》由会员分享,可在线阅读,更多相关《数据结构课程设计报告3.doc(22页珍藏版)》请在三一办公上搜索。

1、课程设计报告题目:在n个城市之间建设网络,只需保证连通即可,求最经济的架设方法。存储结构采用(邻接表和邻接矩阵)两种,采用课本上的两种求解算法。一、需求分析1.1已知一个无向连通网表示n个城市以及城市间可能设置的通信网络线路,其中网的顶点表示城市,边表示两个城市之间的线路,赋于边上的权值表示相应的代价。对于n个点的连通网能建立许多不同的生成树,每一棵生成树都可以是一个通信网。我们要选择一棵生成树,使总的耗费最小。1.2该无向连通图的建立需要使用两种存储结构,即邻接表和邻接矩阵。1.3实现最小生成树需要使用两种算法。即普里姆算法和克鲁斯卡尔。1.4程序通过人机交互实现数据的输入和输出。1.5测试

2、数据 (a,b):2 ; (a,c):3; (a,d):4; (c,d):4; (b,d):5二、概要设计程序分为两大部分存储部分和算法部分;存储部分分为邻接矩阵和邻接表,而且包含了两者直接的互相转换;算法部分分为普里母算法和克鲁斯卡尔算法。1.抽象数据类型图的定义如下ADT Graph数据对象V;V是具有相同特性的数据元素的集合,成为顶点集。数据关系R: R = VRVR = (v,w)|v,w为V集合中的元素,(v,w)表示v和w之间存在的路径基本操作P;CreateMGraph(MGraph *G)初始条件:V是图的顶点集,VR是图的边的集合。操作结果:按V和VR的定义构造图G,用邻接矩

3、阵存储。CreateALGraph(ALGraph *G)初始条件:V是图的顶点集,VR是图的边的集合。操作结果:按V和VR的定义构造图G,用邻接表存储。LocateVex(G,u)初始条件:图G存在,u和G中顶点有相同的特征。操作结果:若G中存在顶点u,则返回该顶点在图中的位置;否则返回其他信息。MiniSpanTree_PRIM(G, u)初始条件:图G存在,u是图G中的一个顶点。操作结果:用普利姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。Kriuskal(G)初始条件:图G存在操作结果:用克鲁斯卡尔算法构造图G的最小生成树T,输出T的各条边。ListToMat(MGra

4、ph *G1,ALGraph *G2)初始条件:图G2存在操作结果:把图的邻接表存储结构转换为邻接矩阵存储结构,用图G1表示。MatToList(MGraph *G1,ALGraph *G2)初始条件:图G1存在操作结果:把图的邻接矩阵存储结构转换为邻接表存储结构,用图G2表示。LocateVex(MGraph *G,VertexType u)初始条件:图G存在,u和G中顶点有相同特征操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1ADT Graph2.主程序 void main()创建图G,并按不同的存储结构输出。对图的存储结构进行转换使用算法构造最小生成树并输出各边3.模块

5、间的调用关系主模块子模块 三、详细设计1.图和顶点的定义#define OK 1#define ERROR 0#define TURE 1#define FALSE 0#define OVERFLOW -1#define INFEASIBLE -2typedef int Status;#define INFINITY 32767 /两地之间没有架设线路的权值为最大数。#define MAX_VERTEX_NUM 20 /城市的数目最大为20#define MAX_NAME 5/城市名称的最大长度为5typedef char VertexTypeMAX_NAME;/城市的名称用字符数组存储typ

6、edef int VRType; /两城市间的关系类型1.1邻接矩阵存储表示的图的结构体类型的定义typedef struct ArcCell VRType adj; /*顶点关系类型。对无权图,用1(是)或0(否)表示相邻否*/ /*对带权全图,则为权值类型*/ ArcCell,AdjMatrixMAX_VERTEX_NUMMAX_VERTEX_NUM;typedef struct VertexType vexsMAX_VERTEX_NUM; /*顶点向量*/ AdjMatrix arcs; /*邻接矩阵*/ int vexnum,arcnum; /*图的当前顶点数和弧数*/ MGraph;

7、 1.2邻接表类型存储表示的图的结构体类型的定义 typedef struct ANode /* 弧的结点结构类型 */ int end; /弧尾在邻接表头结点中的位置 int begin; /弧头在邻接表头结点中的位置 int weight; /* 该弧的相关信息,这里用于存放权值 */ struct ANode *nextarc; /* 指向下一条弧的指针 */ ANode;typedef struct Vnode /* 邻接表头结点的类型 */ VertexType vertex; /* 顶点信息,城市名称 */ int bianhao; /城市在邻接表头结点数组中的相应编号 ANode

8、 *firstarc; /* 指向第一条弧 */ VNode,AdjListMAX_VERTEX_NUM; /* AdjList是邻接表类型 */typedef struct AdjList adjlist; /* 邻接表 */ int vexnum,arcnum; /* 图中顶点数n和边数e */ ALGraph; 2.Prim算法的思想假设V是图中顶点的集合,E是图中边的集合,TE为最小生成树中的边的集合,则prim算法通过以下步骤可以得到最小生成树: (1)初始化:U=u 0,TE=f。此步骤设立一个只有结点u 0的结点集U和一个空的边集TE作为最小生成树的初始形态,在随后的算法执行中,

9、这个形态会不断的发生变化,直到得到最小生成树为止。 (2)在所有uU,vVU的边(u,v)E中,找一条权最小的边(u 0,v 0),将此边加进集合TE中,并将此边的非U中顶点加入U中。此步骤的功能是在边集E中找一条边,要求这条边满足以下条件:首先边的两个顶点要分别在顶点集合U和VU中,其次边的权要最小。找到这条边以后,把这条边放到边集TE中,并把这条边上不在U中的那个顶点加入到U中。这一步骤在算法中应执行多次,每执行一次,集合TE和U都将发生变化,分别增加一条边和一个顶点,因此,TE和U是两个动态的集合,这一点在理解算法时要密切注意。 (3)如果U=V,则算法结束;否则重复步骤2。可以把本步骤

10、看成循环终止条件。我们可以算出当U=V时,步骤2共执行了n1次(设n为图中顶点的数目),TE中也增加了n1条边,这n1条边就是需要求出的最小生成树的边。Prim算法假设网中有N个顶点,则第一个进行初始化的循环语句频度为n,第二个循环语句的频度为n-1。其中有两个内循环;由此普里母算法的时间复杂度为O(n2),与网中的边数无关!3.克鲁斯卡尔算法的思想为假设 WN=(V,E) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:(1)先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。(2)从网的边

11、集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。(3)依次类推,重复上述操作,直至森林中只有一棵树,也即子图中含有 n-1条边为止。克鲁斯卡尔算法至多对e条边各扫描一次时间复杂度为O(eloge)。4.编写程序使用到的函数为 (a)程序中用来实现邻接矩阵和邻接表存储、输出以及互相转化的函数Status InitALGraph(ALGraph *G)/初始化邻接表void CreateALGraph(ALGraph *G)/创建邻

12、接表Status InitMGraph(MGraph *G)/初始化邻接表Status CreateMGraph(MGraph *G)/创建邻接表Status MatToList(MGraph *G1,ALGraph *G2)/将邻接矩阵G1转换成邻接表G2Status ListToMat(MGraph *G1,ALGraph *G2)/将邻接表G1转换成邻接矩阵G2Status PrintMGraph(MGraph *G)/输出邻接矩阵gStatus PrintALGraph(ALGraph *G)/输出邻接表G(b)程序中用来完成prim和kriuskal算法的函数int mininum(

13、minside closedge,MGraph *G)/ 求closedege数组中lowcost的最小正值void MiniSpanTree_PRIM(MGraph *G,VertexType u)/ 用普利姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边void InsertSort(EdgeType E,int n)/对E0.n-1按权值递增有序的进行直接插入排序void Kriuskal(ALGraph *G)/克鲁斯卡尔算法(c) 查找顶点U在图中的位置int LocateVex(MGraph *G,VertexType u)/查找顶点U在图中的位置5.主函数模块为:vo

14、id main()定义邻接矩阵存储结构的图;定义邻接表存储结构的图;选择一种存储结构画出图,并输出;邻接矩阵和邻接表相互转化,得到两种类型的存储图,并输出转换后的图;选择一种算法得到最小生成树并输出生成树的各边。6.模块间的调用层次main()void CreateALGraph(ALGraph *G)Status CreateMGraph(MGraph *G)Status MatToList(MGraph *G1,ALGraph *G2)Status ListToMat(MGraph *G1,ALGraph *G2)void MiniSpanTree_PRIM(MGraph *G,Verte

15、xType u)void Kriuskal(ALGraph *G)Status InitALGraph(ALGraph *G)Status InitMGraph(MGraph *G)Status PrintMGraph(MGraph *G)Status PrintALGraph(ALGraph *G)int mininum(minside closedge,MGraph *G)void InsertSort(EdgeType E,int n)int LocateVex(MGraph *G,VertexType u) 四、编码与测试这个阶段主要是对代码的编写及代码正确性的检验。通过前面的详细设计

16、的分析,这个阶段是完成各个函数的功能,在编程的过程中出现了许多的错误,导致功能的无法实现,出现的错误主要有及心的:1.对于结构体的成员的调用 心得:结构体变量名调用函数时使用符号.,对于结构体指针使用符号-或者是先使用*取得变量名在使用.调用成员。2.函数调用时指针的传递 心得:这个主要是C+与C语言的区别,在C+中函数的参数中有&,表示该变量为返回值数据,而在C语言中,据我所学确没有这样的用法。3.非法字符的使用 心的:非法字符的使用往往让人很难找到错误,而且Win-TC环境给出的提示往往是错误的。产生这种错误的原因是汉语的标识符的出现,往后要注意了。4.字符串的输入及输出心的:对于字符串的

17、输入输出都应使用取地址符号。5数据的输入心的:数据的输入可以使用空格符或取地址符号,但是空格符的输入常常容易发生错误,最好使用换行符。6.程序的输出出现错误的数据心的:程序总是会莫名奇妙的输出错误的信息,有时候输出是错误的,有时候是正确的,很奇怪,建议以后出现这类型情况时先看代码,若没有错误,那就等会再运行一边。7.命令行的消失心的:有时候在输入数据的过程中,命令行就会突然消失,在同学的建议下加了getchar();语句就不出现这类情况了,不明白是为什么。8.命令行重复输出相同的数据心的:这种情况很有可能是出现了死循环,这不仅发生在循环语句的情况下,对于结点指针的指向也会导致是循环。五、综合测

18、试综合测试其实是对程序的总体测试,但在编码阶段已经对语句的进行了测试,在总体测试阶段多采用几组数据,在编码阶段的数据可以简单一些,但在综合测试阶段要用使用比较复杂的数据,可以检测到在编码阶段不宜发现的错误。在综合测试阶段发现的错误:对于邻接表的指针的取向。测试数据:(a,b):2 ; (a,c):3; (a,d):4; (c,d):4; (b,d):5采用邻接表存储的输入及邻接表转换为邻接矩阵并显示通过Prim算法显示最小生成树的各边采用邻接矩阵存储的输入邻接矩阵转换为邻接表并显示及通过Prim算法显示最小生成树的各边通过Kruskal算法显示最小生成数的各边六、课程总结认识: 对于编程,假期

19、一个月的学习里,我已经有了很深刻的体会,搭建框架是十分必要的,只有有了框架才能在具体实现上一步一步的完成。通过这次的课程设计,不仅让我提高了编写程序的能力,同时也让我对大学所学课本的知识有了更好的这学期,我学习了软件工程导论,这门课程主要是对编写软件过程的顺序的介绍,不同的阶段应该完成什么样的任务。按着书上的步骤一步步完成,确实很节省时间。数据结构对于建立n地最小生成树问题是将数据结构的知识运用于实现现实问题,在程序设计过程中对于我来说十分繁杂,在具体实现算法是出现了问题:例如prim算法实现的时候没有办法记录起始点,再输出边的过程中出现错误,经过上网查阅资料才建立了数组将其解决。再调试程序过

20、程中也是相当繁琐,代码写完了但是运行过程中出现了很多错误。编写程序是一件幸苦但又愉快的过程,在学完C语言是并没有什么太多的算法思想,但数据结构给了我很多灵感,有了数据结构的思想很多实际问题就能解决了,主要由于代码接触太少,所以在有了思想的情况下很难实现代码,以后要经常去用代码实现自己的想法,算法对于程序设计十分重要,数据结构可以说是编程者的大脑,没有数据结构代码就失去了运用于实际问题的能力。心得:在课程设计的过程中收获很多,独立思考是我首先觉悟到的,因为起初在看到繁杂的代码满脑子只有愤怒,自己根本没有办法实现,可后来在经过上网查阅思想和数据结构书我才慢慢的有了自己的想法。最后渐渐的喜欢上了代码

21、,课程设计的确让我有一种成为编程人员的感觉了,经过努力我终于完成了本次课程设计,通过这次课程设计,我感觉到要真正做出一个程序并不很容易,但只要用心去做,总会有收获,特别是当我遇到 一个问题,想办法去解决,最后终于找到方法时,心里的那份喜悦之情真是难以形容。编写程序中遇到问题再所难免,应耐心探究其中的原因,从出现问题的地方起,并联系前后程序,仔细推敲,逐个排查。直到最终搞清为止。我们本次做的是图的做小生成树问题,深刻的体会到它的实用性。通过本次课程设计我们发现我们对于C语言和数据结构还有很多地方不知道,今后需要努力学习。-参考文献:1 李云清,杨庆红.数据结构(C语言版).北京:人民邮电出版社,

22、2004.2 严蔚敏,吴伟民.数据结构(C语言版).北京:清华大学出版.1997.3 苏光奎,李春葆.数据结构导学.北京:清华大学出版.2002. 4 周海英,马巧梅,靳雁霞.数据结构与算法设计.北京:国防工业出版社,2007.5 张海藩. 软件工程导论. 北京:清华大学出版社.2003.6互联网附录:程序清单#include #include #define OK 1#define ERROR 0#define TURE 1#define FALSE 0#define OVERFLOW -1#define INFEASIBLE -2typedef int Status;#define INF

23、INITY 32767#define MAX_VERTEX_NUM 20#define MAX_NAME 5typedef char VertexTypeMAX_NAME;typedef int VRType;typedef struct ArcCell VRType adj; /*顶点关系类型。对无权图,用1(是)或0(否)表示相邻否*/ /*对带权全图,则为权值类型*/ ArcCell,AdjMatrixMAX_VERTEX_NUMMAX_VERTEX_NUM;typedef struct VertexType vexsMAX_VERTEX_NUM; /*顶点向量*/ AdjMatrix

24、arcs; /*邻接矩阵*/ int vexnum,arcnum; /*图的当前顶点数和弧数*/ MGraph; /* 以下定义邻接表类型 */typedef struct ANode /* 弧的结点结构类型 */ int end; int begin; /* 该弧的终点位置 */ int weight; /* 该弧的相关信息,这里用于存放权值 */ struct ANode *nextarc; /* 指向下一条弧的指针 */ ANode;typedef struct Vnode /* 邻接表头结点的类型 */ VertexType vertex; /* 顶点信息 */ int bianhao

25、; ANode *firstarc; /* 指向第一条弧 */ VNode,AdjListMAX_VERTEX_NUM; /* AdjList是邻接表类型 */typedef struct AdjList adjlist; /* 邻接表 */ int vexnum,arcnum; /* 图中顶点数n和边数e */ ALGraph; /* 图的邻接表类型 */int LocateVex(MGraph *G,VertexType u) /*初始条件:图G存在,u和G中顶点有相同特征*/ /*操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1*/ int i; for(i=0;ivex

26、num;+i) if(strcmp(u,G-vexsi)=0) return i; return -1;/* 建立无向图的邻接表算法 */Status InitALGraph(ALGraph *G) int i ; printf(请输入城市的数量及城市间的路径数目n); scanf(%d%d,&G-vexnum,&G-arcnum); for(i=0;i vexnum;i+) /* 建立顶点表 */ printf(请输入第%d个城市的名称n,i); scanf(%s,&G-adjlisti.vertex); /* 读入顶点信息 */ G-adjlisti.firstarc=NULL;/* 边表

27、置为空表 */ G-adjlisti.bianhao = i; printf(每个城市所对应的序号为n); for(i = 0;ivexnum;i+) printf(%d-%s ,i,&G-adjlisti.vertex); return OK;Status PrintALGraph(ALGraph *G) int i,end,begin,weight; ANode *s; for(i=0;ivexnum;i+)/* 建立顶点表 */ printf(%s -,&G-adjlisti.vertex); s = G-adjlisti.firstarc; while(s!=NULL) printf(

28、 %s,%s ):%d ,&G-adjlists-end.vertex,&G-adjlists-begin.vertex,s-weight); s = s-nextarc; printf(n); return OK;void CreateALGraph(ALGraph *G) int i,j,k,weight; ANode *s; InitALGraph (G); for(k=0;k arcnum;k+) /* 建立边表 */ printf(请输入第%d条边的两个城市的编号及路径的架设费用n,k); scanf(%d,&i); scanf(%d,&j); scanf( %d,&weight);

29、/* 读入边(vi,vj)的顶点对序号 */ s=( ANode *)malloc(sizeof(ANode); /* 生成边表结点 */ if(!s) printf(申请空间失败!n); exit(OVERFLOW); s- begin=j; /* 邻接点序号为j */ s-end = i; s-weight = weight; s-nextarc= G-adjlisti.firstarc; G-adjlisti.firstarc=s; /* 将新结点*s插入顶点vi的边表头部 */ s=(ANode*)malloc(sizeof(ANode); if(!s) printf(申请空间失败!n

30、); exit(OVERFLOW); s- begin=i; /* 邻接点序号为i */ s-end = j; s-weight = weight; s-nextarc=G-adjlistj.firstarc; G-adjlistj.firstarc=s; /* 将新结点*s插入顶点vj的边表头部 */ PrintALGraph(G);/* CreateALGraph */Status PrintMGraph(MGraph *G) int a; int i,j; printf( ); for(i=0;ivexnum;+i) printf( %s ,&G-vexsi); printf(n); f

31、or ( i=0; ivexnum; i+) printf( %s ,&G-vexsi); for ( j=0; jvexnum; j+) printf( %5d ,G-arcsij.adj); printf(n); return OK;Status InitMGraph(MGraph *G) int i,j; printf(请输入城市的数量及城市间的路径数目n); scanf(%d%d,&G-vexnum,&G-arcnum); printf(n请依次输入城市的名称,字符串类型n); for(i=0;ivexnum;+i) /*构造顶点向量*/ scanf(%s,&G-vexsi); for

32、(i=0;ivexnum;+i) /*初始化邻接矩阵*/ for(j=0;jvexnum;+j) G-arcsij.adj=INFINITY; return OK;Status CreateMGraph(MGraph *G)/*采用数组(邻接矩阵)表示法,构造无向网G*/ int i,j,k,weight,IncInfo; VertexType va,vb; InitMGraph(G); for(k=0;karcnum;+k) printf(请输入第%d条路径的起点城市和终点城市的名称及路径的架设费用n,k); scanf(%s %s %d,&va,&vb,&weight); i=Locate

33、Vex(G,va); j=LocateVex(G,vb); G-arcsij.adj=weight; G-arcsji.adj=weight; PrintMGraph(G); return OK;typedef struct/*记录从顶点集U到V-U的代价最小的边的辅助数组定义*/ VertexType adjvex; VRType lowcost;minsideMAX_VERTEX_NUM;int mininum(minside closedge,MGraph *G)/*求closedege,lowcost的最小正值*/ int i=0,j,k,min; while(!closedgei.l

34、owcost) i+; min=closedgei.lowcost; k=i; for(j=i+1;jvexnum;j+) if(closedgej.lowcost0) if(minclosedgej.lowcost) min=closedgej.lowcost; k=j; return k;void MiniSpanTree_PRIM(MGraph *G,VertexType u)/*用普利姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边*/ int i,j,k; int qidian,zhongdian,weight; VertexType va,vb; minside clo

35、sedge; k=LocateVex(G,u); for(j=0;jvexnum;+j) /*辅助数组初始化*/ if(j!=k) strcpy(closedgej.adjvex,u); closedgej.lowcost=G-arcskj.adj; closedgek.lowcost=0; /*初始U=u*/ printf(最小代价生成树的各条边为:n); for(i=1;ivexnum;+i) /*选择其余G.vexnum-1个顶点*/ k=mininum(closedge,G); /*求出T的下一个结点:第K顶点*/ strcpy( va,closedgek.adjvex); strcp

36、y(vb ,G-vexsk); qidian=LocateVex(G,va); zhongdian=LocateVex(G,vb); weight = G-arcsqidianzhongdian.adj; printf(weight(%s,%s)=%dn,va,vb,weight); /*输出生成树的边*/ closedgek.lowcost=0; /*第K顶点并入U集*/ for(j=0;jvexnum;+j) if(G-arcskj.adjvexsk); closedgej.lowcost=G-arcskj.adj; void InsertSort(ANode *E,int n)/* 对E

37、0.n-1按权值递增有序的进行直接插入排序 */ int i,j; ANode temp; for(i=1;i=0&temp.weightvexnum; E=(struct ANode*)malloc(n*sizeof(struct ANode); k=0; for(i=0;ivexnum;i+) /* 将各边存到E0.n数组中 */ for(j=0;jvexnum;j+) s = G-adjlisti.firstarc; while(s!=NULL) (E+k)-end = s-end; (E+k)-begin = s-begin; (E+k)-weight = s-weight ; s = s-nextarc; k+; InsertSort(E,k); /* 对E数组按w递增排序 */ for(i=0;ivexnum;i+) vseti=i; /* 初始化辅助数组 */ k=1; j=0; while(kvexnum) /* 生成的边数小于n时循环 */ end=(E+j)-end; begin=(E+j)-begin; /* 取一条边的头尾顶点 */ sn1=vsetend; sn2=vsetbegin;/* 分别得到两个顶点所属的集合编号 */ if(sn1!=sn2)

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

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号