1、I成 绩 评 定 表学生姓名 冯有礼 班级学号 1009010118专 业 信息与计算科学课程设计题目 1.最小生成树解决城市联络网建设问题 2.线性表的插入,删除,添加。评语组长签字:成绩日期 20 年 月 日II课程设计任务书学 院 理学院 专 业 信息与计算科学学生姓名 冯有礼 班级学号 1009010118课程设计题目 1.最小生成树解决城市联络网建设问题 2.线性表的插入,删除,添加。实践教学要求与任务:1、巩固和加深对数据结构基本知识的理解。2、初步掌握简单软件的分析方法和设计方法。3、了解与课程有关的工程技术规范,能正确解释和分析设计结果。4、具体任务(1)最小生成树解决城市联络
2、网建设问题(2)线性表的插入,删除,添加。工作计划与进度安排:第一天 查阅资相关料; 第二、三天 程序设计; 第四程序调试; 第五天天 答辩指导教师:201 年 月 日专业负责人:201 年 月 日学院教学副院长:201 年 月 日III摘 要“数据结构”是有关计算技术及信息管理技术专业的一门必修的核心课程。数据结构课程的任务实在讨论在应用问题求解时数据的逻辑组织、在计算机中的存储实现以及相关操作的算法设计。数据结构课程目的是使学生掌握在实际问题解决过程中组织数据、存储数据和处理数据的基本方法,为以后从事软件开发和应用,为进一步学习后续课程打下坚实的基础。本文第一个问题是针对随着现代网络的高速
3、发展,从成本角度出发,要求所假设的光缆长度最短,故而采用最小生成树来建模此问题。本文给出了一个城市间光缆假设的场景,采用 Prim 算法、Kruskal 算法两种算法解决该城市间光缆假设问题,并通过实验仿真分别实现这两种算法,得到了城市联络网建设的最佳解决方案。本文第二个问题是根据本学期对数据结构中线性表的学习,编写了一个程序,完成线性表的插入,删除,和查找功能。关键词:最小生成树;Prim 算法;Kruskal 算法;线性表IV目 录1.最小生成树解决城市联络网建设问题 11.1 问题描述 .11.2 问题分析 .11.3 算法分析 .21.4 算法实现及结果分析 52.线性表的插入删除查找
4、程序 72.1 问题描述 .72.2 问题分析 .72.3 算法分析 .82.4 运行结果 .9总 结 10参考文献 .11附录源程序代码 1211.最小生成树解决城市联络网建设问题1.1 问题描述假设要在 个城市之间建立通信联络网,其中顶点表示城市,边表示城市n之间是否有通路,边上的权值表示在两者间建立通信链路的花费,要求使得任意两市之间都有通信链路,并且使得总的建设费用最少。显然,我们会想到连通 个城市只需要 条线路,在每两个城市之间都n1n可以设置一条线路,相应地都要付出一定的经济代价。 个城市之间,最多可以设置 条线路,那么,如何在这些可能的线路中选择 条,使得总2/)1(n 1n的耗
5、费最少呢?根据所学的知识,我们知道可以通过寻找最小生成树来解决这个问题。下面我们以图 1 为例,运用普利姆算法以及克鲁斯卡尔算法来解决城市间通信网建立问题。ADCE FB12 345671 089图 11.2 问题分析在一个具有几个顶点的连通图 中,如果存在子图 包含 中所有顶点和GG一部分边,且不形成回路,则称 为图 的生成树,代价最小生成树则称为最小生成树。最小生成树有个重要的性质 MST 性质(最小生成树性质):设是一个连通网络, 是顶点集 的一个真子集。若 是 中一EVN,UVVU,条“一个端点在 中(例如: ),另一个端点不在 中的边,且 具有,2最小权值,则一定存在 的一棵最小生成
6、树包括此边 。多数算法利用这GVU,个性质来求解最小生成树,本文用到的普里姆算法和克鲁斯卡尔算法均利用了这个性质,同时它们也属于贪心算法。贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。本文中的城市通信网建设问题要求使得任意两市之间都有通信链路,并且使得总的建设费用最少,故而适合用贪心算法求解。1.3 算法分析1)Prim 算法 假设 是图中顶点的集合, 为最小生成树中的边的集合,
7、则 算法通VTEprim过以下步骤可以得到最小生成树:1:初始化: , 。此步骤设立一个只有结点 的结点集VuU00u和一个空的边集 作为最小生成树的初始形态,在随后的算法执行中,这个形态会不断的发生变化,直到得到最小生成树为止。2:在所有 边中,找一条权最小的边 ,将此边加进集合 中,0,vuTE并将此边的非 中顶点加入 中。此步骤的功能是在边集 中找一条边,要求这条边满足以下条件:首先边的两个顶点要分别在顶点集合 和 中,其次UV边的权要最小。找到这条边以后,把这条边放到边集 中,并把这条边上不在TE中的那个顶点加入到 中。这一步骤在算法中应执行多次,每执行一次,集合UU和 都将发生变化,
8、分别增加一条边和一个顶点,因此, 和 是两个动态TE的集合,这一点在理解算法时要密切注意。3:如果 ,则算法结束;否则重复步骤 2。可以把本步骤看成循环终止条V件。我们可以算出当 时,步骤 2 共执行了 次(设 为图中顶点的数目),1n中也增加了 条边,这 条边就是需要求出的最小生成树的边。TE1n1nPrim 算法伪代码如下:void MiniSpanTree_PRIM(MGraph G,VertexType u) /用普利姆算法从第 u 个顶点出发构造网 G 的最小生成树 T,输出 T 的各条3边。/记录从顶点集 U 到 V-U 的代价最小的边得辅助数组定义/ struct/ Vertex
9、Type adjvex;/ VRType lowcost;/ closedgeMAX_VERTEX_NUM;k=LocateVex(G,u);for(j=0;j0, vi UVviPrintf(closedgek.adjvex,G.vexsk); /输出生成树的边closedgek.lowcost=0; /第 k 顶点并入 U 集for(j=0;jnextarc)/对 v0 的每个邻接顶点检查w=p-adjvex; /w 为 v0 的邻接顶点if(visitedw=0) /w 未曾访问,是 v0 的孩子DFSArticul(G,w); /返回前求得 lowwif(loww=visitedv0)
10、 printf(v0,G.verticesv0.data); /关节点else if(visitedwL-length+1) return ERROR; if (L-length =L-listsize)L-elem = (ElemType * )realloc(L-elem,(L-listsize + LISTINCREMENT) * sizeof (ElemType);if (!L-elem )exit(OVERFLOW); L-listsize += LISTINCREMENT; q = for (p = p=q;-p)*(p+1) = *p; *q = e ; +L-length ;
11、return OK ;Status LocateElem_Sq(SqList L, ElemType e) /顺序表的查找int i=1;ElemType *p;p =L.elem; while (iL-length) return ERROR;p=e=*p;q=L-elem+L-length-1;for(+p;plength;printf(“%3dn“,e);return OK;92.4 运行结果10总 结通过本次课程设计,使我对数据结构程序的设计方法、步骤、思路、有一定的了解与认识。在课程设计过程中按照规定的程序进行,先针对题目收集、调查有关资料,然后进入程序调试阶段,其间与指导教师进行讨
12、论、修改,再讨论、再修改,最后定案,进行写论文阶段。整个过程周密有序,按时高质完成全部课程设计。此次课程设计按照设计任务书、指导书、技术条件的要求进行顺利完成任务,加深了对数据结构这么课程的了解,在程序调试以及实现过程中,进一步了解数据结构中的原理,理论,对知识的理解进一步深化11参考文献1吴伟民.数据结构(C 语言版).北京:清华大学出版社,20092姚诗斌.数据结构基础.北京:北京大学出版社,19933严蔚敏.并行算法引论.天津:石油工业出版社,19924胡蕴超.算法与数据结构.北京:电子工业出版社,199312附录源程序代码1 最小生成树解决城市联络网建设问题源程序代码#includeu
13、sing namespace std;#include const int maxvertexnum=20;const int maxedgenum=40;typedef int adjmatrixmaxvertexnummaxvertexnum;struct edgenodeint frontvex;int rearvex;int weight;typedef edgenode adgesetmaxedgenum;/=void insitadj(adjmatrix void setadj(adjmatrix void fun(adjmatrix GA,adgeset void display
14、(adgeset GT,int n);void insit(adgeset /=void insit(adgesetiGAij;for(i=0;in;adgeset GT;adjmatrix GA;insitadj(GA);setadj(GA,n);insit(GT,n,GA);fun(GA,GT,n);display(GT,n);int x;cinx;return 0;2.线性表的插入,删除,添加的源程序:#include #include #define OK 1#define ERROR 0 #define OVERFLOW -1typedef int ElemType; typedef
15、 int Status;#define LIST_INIT_SIZE 100#define LISTINCREMENT 10typedef structElemType *elem;int length; int listsize; 15SqList;Status InitList_Sq(SqList *L)int i,n;L-elem = (ElemType * )malloc(LIST_INIT_SIZE*sizeof(ElemType);if (! L-elem) exit (OVERFLOW);printf(“您希望您的线性表有几个元素: “);scanf(“%d“,printf(“n
16、“);printf(“输入您的%d 个元素,以构建顺序表: n“,n);for(i=1;ielemi-1);L-length = n;L-listsize = LIST_INIT_SIZE; return OK;/InitList_SqStatus PrintList_Sq(SqList L)int i;printf(“顺序表中的元素为: “);for (i=1;iL-length+1) return ERROR; if (L-length =L-listsize)L-elem = (ElemType * )realloc(L-elem,(L-listsize + LISTINCREMENT)
17、 * sizeof (ElemType);if (!L-elem )exit(OVERFLOW); L-listsize += LISTINCREMENT; q = for (p = p=q;-p)*(p+1) = *p; *q = e ; +L-length ; return OK ;/ListInsert_SqStatus LocateElem_Sq(SqList L, ElemType e)16int i=1;ElemType *p;p =L.elem; while (iL-length) return ERROR;p=e=*p;q=L-elem+L-length-1;for(+p;pl
18、ength;printf(“%3dn“,e);return OK;void main()SqList L;ElemType k,e;int i,j,m; if (InitList_Sq(printf(“输出程序中的元素n“);PrintList_Sq(L);printf(“n 请输入所需插入的位置和您要插入的元素:“);printf(“ninput i,e=“); scanf(“%d%d“,if (ListInsert_Sq(else PrintList_Sq(L);printf(“n“);printf(“请输入您要查找的元素:“);scanf(“%d“,m=LocateElem_Sq ( L,k);if(m)printf(“n 您要查找的元素是这个线形表的第%d 个元素n“,m);else printf(“对不起,该线形表中不存在这个元素n“);17printf(“n 请输入要删除的第几个元素:j=“);scanf(“%d“,printf(“n“);if (ListDelete_Sq(else PrintList_Sq(L);printf(“n“);