数据结构课程设计指导书.docx
《数据结构课程设计指导书.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计指导书.docx(16页珍藏版)》请在冰豆网上搜索。
数据结构课程设计指导书
数据结构课程设计指导书
长春工业大学人文信息学院
2011-3
1前言
1.1概述
数据结构是一门实践性很强的课程,只靠读书和做习题是不能提高实践能力的,尤其是在数据结构中要解决的问题更接近于实际。
数据结构的课程设计是对学生的一种全面的综合训练,与程序设计语言课程中的课程设计不同,数据结构课程设计属于创造性的活动,需要学生自己进行问题分析、进行数据结构和算法的设计、再上机调试和测试程序。
数据结构课程设计是一种自主性很强的学习过程,其教学目的主要有两个:
⑴深化理解和掌握书本上的理论知识,将书本上的知识变“活”;⑵理论和实践相结合,使学生学会如何把书本上有关数据结构和算法的知识用于解决实际问题,培养数据结构的应用能力和软件工程所需要的实践能力。
为了达到上述目的,本学期数据结构课程设计题目如下:
1.数组的循环移位
2.约瑟夫环问题
3.求二叉树中叶子结点的个数
4.判断两棵二叉树是否相似
5.信号放大器
6.Huffman编码
7.机器调度问题
8.医院选址问题
9.简单个人电话号码查询系统
10.各种排序算法时间性能的比较
11.机器调度问题
1.1.2实验的一般步骤
1.预备知识的学习
需要学生在实验前复习实验所用的预备知识。
这需要学生有自主的学习意识和整理知识的能力。
2.上机前的准备
将实现提示中给出的数据类型和算法转换为对应的程序,并进行静态检查,尽量减少语法错误和逻辑错误。
上机前的充分准备能高效利用机时,在有限的时间内完成更多的实验内容。
3.上机调试和测试程序
调试程序是一个辛苦但充满乐趣的过程,也是培养程序员素质的一个重要环节。
很多学生都有这样的经历:
化了好长时间去调试程序,错误却越改越多。
究其原因,一方面,是对调试工具不熟悉,出现了错误提示却不知道这种错误是如何产生的;另一方面,没有认识到努力预先避免错误的重要性,也就是对程序进行静态检查。
对程序进行测试,首先需要设计测试数据。
在数据结构中测试数据需要考虑两种情况:
⑴一般情况:
例如循环的中间数据、随机产生的数据等;⑵特殊情况:
例如循环的边界条件、数据结构的边界条件等。
4.课程设计报告
在课程设计完成相关题目后要总结和整理的报告。
2题目概述
2.1数组的循环移位
1.问题描述
对于一个给定的整型数组循环右移i位。
2.基本要求
⑴在原数组中实现循环右移,不另外申请空间;
⑵时间性能尽可能好;
⑶分析算法的时间复杂度。
3.设计思想
将这个问题看作是把数组ab转换成数组ba(a代表数组的前i个元素,b代表数组中余下的n-i个元素),先将a逆置得到arb,再将b逆置得到arbr,最后将整个arbr逆置得到(arbr)r=ba。
设Reverse函数执行将数组元素逆置的操作,对abcdefgh向左循环移动3个位置的过程如下:
Reverse(0,i-1);//得到cbadefgh
Reverse(i,n-1);//得到cbahgfed
Reverse(0,n-1);//得到defghabc
具体分析过程请参见主教材第一章思想火花。
4.算法描述
2.2约瑟夫环问题
1.问题描述
设有编号为1,2,……,n的n(n>0)个人围成一个圈,每个人持有一个密码m,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。
当任意给定n和m后,设计算法求n个人出圈的次序。
2.基本要求
⑴建立模型,确定存储结构;
⑵对任意n个人,密码为m,实现约瑟夫环问题;
⑶出圈的顺序可以依次输出,也可以用一个数组存储。
3.设计思想
首先,设计实现约瑟夫环问题的存储结构。
由于约瑟夫环问题本身具有循环性质,考虑采用循环链表,为了统一对表中任意结点的操作,循环链表不带头结点。
将循环链表的结点定义为如下结构类型:
structNode
{
intdata;//编号
Node*next;
};
其次,建立一个不带头结点的循环链表并由头指针first指示。
具体算法请参见2.1.2自行设计。
最后,设计约瑟夫环问题的算法。
下面给出伪代码描述,操作示意图如图2-1所示。
2.3求二叉树中叶子结点的个数
1.问题描述
已知一棵二叉树,求该二叉树中叶子结点的个数。
2.基本要求
⑴采用二叉链表作存储结构;
⑵设计递归算法求叶子结点的个数。
3.设计思想
求二叉树中叶子结点的个数,即求二叉树的所有结点中左、右子树均为空的结点个数之和。
因此可以将此问题转化为遍历问题,在遍历中“访问一个结点”时判断该结点是不是叶子,若是则将计数器累加。
算法如下:
2.4判断两棵二叉树是否相似
1.问题描述
设计算法判断给定的两棵二叉树是否相似。
两棵二叉树当且仅当满足以下条件,称这两棵二叉树是相似的:
⑴他们都为空或都只有一个根结点;
⑵他们的左右子树也相似。
2.基本要求
⑴采用二叉链表作存储结构;
⑵设计递归算法判断两棵二叉树是否相似。
3.设计思想
由二叉树相似的定义,得到如下判定两棵二叉树s和t是否相似的递归函数Like:
⑴若s=t=NULL,则s和t相似,即Like(s,t)=1;
⑵若s和t中有一个为NULL,另一个不为NULL,则s和t不相似,即Like(s,t)=0;
⑶进一步判断s的左子树和t的左子树、s的右子树和t的右子树是否相似。
具体算法如下:
2.5信号放大器
1.问题描述
天然气经过管道网络从其生产基地输送到消耗地,在传输过程中,其性能的某一个或几个方面可能会有所衰减(例如气压)。
为了保证信号衰减不超过容忍值,应在网络中的合适位置放置放大器以增加信号(例如电压)使其与源端相同。
设计算法确定把信号放大器放在何处,能使所用的放大器数目最少并且保证信号衰减不超过给定的容忍值。
2.基本要求
⑴建立模型,设计数据结构;
⑵设计算法完成放大器的放置;
⑶分析算法的时间复杂度。
3.设计思想
为了简化问题,假设分布网络是二叉树结构,源端是树的根结点,信号从一个结点流向其孩子结点,树中的每一结点(除了根)表示一个可以用来放置放大器的位置。
如下图是一个网络示意图,边上标出的是从父结点到子结点的信号衰减量。
对于网络中任一结点i,设d(i)表示结点i与其父结点间的衰减量,D(i)为从结点i到结点i的子树中任一叶子结点的衰减量的最大值,并有如下递推公式:
在此公式中,要计算某结点的D值,必须先计算其孩子结点的D值,因而必须后序遍历二叉树,当访问一个结点时,计算其D值。
例如,D(B)=max{D(D)+d(D),D(E)}=4,若容忍值为3,则在B点或其祖先的任意一点放置放大器,并不能减少B与其后代的衰减量,必须在D点放置一个放大器或在其孩子结点放置一个或多个放大器。
若在结点D处放置一个放大器,则D(B)=2。
根据上述分析,设计如下存储结构:
structelement
{
intD;//该结点的衰减量
intd;//父结点的衰减量
boolboost;//当且仅当本处设置放大器,则boost为true
};
structBiNode
{
elementdata;
BiNode*lchild,*rchild;
};
计算并放置放大器的伪代码为:
2.6Huffman编码
1.问题描述
设某编码系统共有n个字符,使用频率分别为{w1,w2,…,wn},设计一个不等长的编码方案,使得该编码系统的空间效率最好。
2.基本要求
⑴设计数据结构;
⑵设计编码算法;
⑶分析时间复杂度和空间复杂度。
3.设计思想
利用Huffman编码树求得最佳的编码方案。
根据哈夫曼算法,建立哈夫曼树时,可以将哈夫曼树定义为一个结构型的一维数组HuffTree,保存哈夫曼树中各结点的信息,每个结点包括:
权值、左孩子、右孩子、双亲,如下图所示。
由于哈夫曼树中共有2n-1个结点,并且进行n-1次合并操作,所以该数组的长度为2n-1。
构造哈夫曼树的伪代码如下:
在哈夫曼树中,设左分支为0,右分支为1,从根结点出发,遍历整棵哈夫曼树,求得各个叶子结点所表示字符的哈夫曼编码。
2.7TSP问题
1.问题描述
所谓TSP问题是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次,并要求所走的路程最短。
该问题又称为货郎担问题、邮递员问题、售货员问题,是图问题中最广为人知的问题。
2.基本要求
⑴上网查找TSP问题的应用实例;
⑵分析求TSP问题的全局最优解的时间复杂度;
⑶设计一个求近似解的算法;
⑷分析算法的时间复杂度。
3.设计思想
对于TSP问题,一种最容易想到的也肯定能得到最佳解的算法是穷举法,即考虑所有可能的旅行路线,从中选择最佳的一条。
但是用穷举法求解TSP问题的时间复杂度为Ο(n!
),当n大到一定程度后是不可解的。
本实验只要求近似解,可以采用贪心法求解:
任意选择某个城市作为出发点,然后前往最近的未访问的城市,直到所有的城市都被访问并且仅被访问一次,最后返回到出发点。
为便于查找离某顶点最近的邻接点,可以采用邻接矩阵存储该图。
算法用伪代码描述如下:
2.8医院选址问题
1.问题描述
n个村庄之间的交通图可以用有向网图来表示,图中边上的权值表示从村庄i到村庄j的道路长度。
现在要从这n个村庄中选择一个村庄新建一所医院,问这所医院应建在哪个村庄,才能使所有的村庄离医院都比较近?
2.基本要求
⑴建立模型,设计存储结构;
⑵设计算法完成问题求解;
⑶分析算法的时间复杂度。
3.设计思想
医院选址问题实际是求有向图中心点的问题。
首先定义顶点的偏心度。
设图G=(V,E),对任一顶点k,称E(k)=max{d(i,k)}(i∈V)为顶点k的偏心度。
显然,偏心度最小的顶点即为图G的中心点。
如图6-2(a)所示是一个带权有向图,其各顶点的偏心度如图(b)所示。
医院选址问题的算法用伪代码描述如下:
2.9简单个人电话号码查询系统
1.问题描述
人们在日常生活中经常需要查找某个人或某个单位的电话号码,本实验将实现一个简单的个人电话号码查询系统,根据用户输入的信息(例如姓名等)进行快速查询。
2.基本要求
⑴在外存上,用文件保存电话号码信息;
⑵在内存中,设计数据结构存储电话号码信息;
⑶提供查询功能:
根据姓名实现快速查询;
⑷提供其他维护功能:
例如插入、删除、修改等。
3.设计思想
由于需要管理的电话号码信息较多,而且要在程序运行结束后仍然保存电话号码信息,所以电话号码信息采用文件的形式存放到外存中。
在系统运行时,需要将电话号码信息从文件调入内存来进行查找等操作,为了接收文件中的内容,要有一个数据结构与之对应,可以设计如下结构类型的数组来接收数据:
constintmax=10;
structTeleNumber
{
stringname;//姓名
stringphoneNumber;//固定电话号码
stringmobileNumber;//移动电话号码
stringemail;//电子邮箱
}Tele[max];
为了实现对电话号码的快速查询,可以将上述结构数组排序,以便应用折半查找,但是,在数组中实现插入和删除操作的代价较高。
如果记录需频繁进行插入或删除操作,可以考虑采用二叉排序树组织电话号码信息,则查找和维护都能获得较高的时间性能。
更复杂地,需要考虑该二叉排序树是否平衡,如何使之达到平衡。
2.10各种排序算法时间性能的比较
1.问题描述
对本章的各种排序方法(直接插入排序、希尔排序、起泡排序、快速排序、直接选择排序、堆排序和归并排序)的时间性能进行比较。
2.基本要求
⑴设计并实现上述各种排序算法;
⑵产生正序和逆序的初始排列分别调用上述排序算法,并比较时间性能;
⑶产生随机的初始排列分别调用上述排序算法,并比较时间性能。
3.设计思想
上述各种排序方法都是基于比较的内排序,其时间主要消耗在排序过程中进行的记录的比较次数和移动次数,因此,统计在相同数据状态下不同排序算法的比较次数和移动次数,即可实现比较各种排序算法的目的。
直接插入排序、起泡排序、直接选择排序在8.1中已经实现,请仿照8.1中的方法在其他排序算法中的适当位置插入计数器统计元素的比较次数和移动次数。
2.11机器调度问题
1.问题描述
机器调度是指有m台机器需要处理n个作业,设作业i的处理时间为ti,则对n个作业进行机器分配,使得:
⑴一台机器在同一时间内只能处理一个作业;
⑵一个作业不能同时在两台机器上处理;
⑶作业i一旦运行,则需要ti个连续时间单位。
设计算法进行合理调度,使得在m台机器上处理n个作业所需要的处理时间最短。
2.基本要求
⑴建立问题模型,设计数据结构;
⑵设计调度算法,为每个作业分配一台可用机器;
⑶给出分配方案。
3.设计思想
假设有七个作业,所需时间分别为{2,14,4,16,6,5,3},有三台机器,编号分别为m1、m2和m3。
这七个作业在三台机器上进行调度的情形如图8-2所示,阴影区代表作业的运行区间。
作业4在0到16时间被调度到机器1上运行,在这16个时间单位中,机器1完成了对作业4的处理;作业2在0到14时间被调度到机器2上处理,之后机器2在14到17时间处理作业7;在机器3上,作业5在0~6时间完成,作业6在6~11时间完成,作业3在11~15时间完成,作业1在15~17时间完成。
注意到作业i只能在一台机器上从si时刻到si+ti时间完成且任何机器在同一时刻仅能处理一个作业,因此最短调度长度为17。
在上述处理中,采用了最长时间优先(LPT)的简单调度策略。
在LPT算法中,作业按其所需时间的递减顺序排列,在分配一个作业时,将其分配给最先变为空闲的机器。
下面设计完成LPT算法的存储结构。
·为每个机器设计数据类型:
structMachineNode
{
intID;//机器号
intavail;//机器可用时刻
};
·为每个作业设计数据类型:
structJobNode
{
intID;//作业号
inttime;//处理时间
};
LPT算法用伪代码描述如下: