数据结构课程设计报告第九组 2.docx
- 文档编号:26269090
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:126
- 大小:1.13MB
数据结构课程设计报告第九组 2.docx
《数据结构课程设计报告第九组 2.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告第九组 2.docx(126页珍藏版)》请在冰豆网上搜索。
数据结构课程设计报告第九组2
数据结构
课程设计报告
题目:
宿舍管理系统,纸牌游戏,
猴子吃桃,简易文本编辑器,
二叉排序树树的实现
设计者:
孟欣,沈学发,陈健维,曾炳忠
陈法威,李智超,李斯恺
专业班级:
软件设计111班
学号:
20110411428、29、30、31
33、34、36
指导教师:
谌颃
所属系部:
计算机科学与技术系
2013年6月11日
一、宿舍管理系统
1、方案设计
1.1任务
为宿舍管理人员编写一个宿舍管理查询软件
1.1.1程序设计要求:
①采用交互工作方式
②建立数据文件,数据文件按关键字(姓名、学号、房号)进行排序(冒泡、选择、插入排序等任选一种)
1.1.2开发设计思想
基于以上系统设计目标本文在开发人事管理信息系统时遵循了以下开发设计思想:
(1)采用现有的软硬件环境及先进的管理系统开发方案从而达到充分利用现有资源提高系统开发水平和应用效果的目的。
(2)尽量达到操作过程中的直观、方便、实用、安全等要求。
(3)系统采用模块化程序设计方法既便于系统功能的各种组合和修改又便于未参与开发的技术维护人员补充、维护。
1.1.3查询菜单:
(用二分查找实现以下操作)
①按姓名查询
②按学号查询
③按房号查询
1.1.4打印任一查询结果(可以连续操作)
1.2功能
根据上述要求,我们开始考虑系统应具备的功能:
①要实现交互工作方式,各项操作结束后均应返回主菜单;
②系统本无任何信息数据,要建立数据文件,需开发一个信息录入功能,即首先创建一个学员线性表,同时我们可以将数据暂时保存在内存中,所以我们未开发信息存盘功能;
③信息录入后都保存在内存中,用户看不到,需要设计一个信息显示功能,信息的显示应该便于查阅,所以需具备按各种关键字显示的功能;
④本系统按关键字(姓名、学号、房号)进行冒泡排序,采用二分查找方式分别实现按关键字(姓名、学号、房号)查询功能;
⑤由于有些同学因为不同原因而离校,所以设计了删除功能;
⑥由于有新同学入校,所以设计了插入功能;
⑦当用户操作完毕需要退出时,我们提供了退出选项,便于使用者退出交互式工作系统。
2、算法设计
2.1线性表的顺序存储
2.1.1存储结构
本系统定义的存储结构采用结构体数组,结构体为:
typedefstruct//定义结构体成员
{
charname[20];
intnum;//学号和房号都为整型
introom;
}stu;
stustud;
typedefstruct
{
intlength;//当前长度
stu*elem;//存储空间基址
intlistsize;//当前分配的存储容量
}linklist;在此说明每个部分的算法设计说明(可以是描述算法的流程图)
2.1.2程序流程图
3、调试分析
3.1使用方法
首先,运行程序进入“欢迎进入宿舍管理查询系统”界面,然后进入线性表创建界面中,输入学生的信息,创建好学生信息以后单击“n”键则进入操作界面(主界面),然后可按键进行操作。
单击数字键“1”,则为按姓名排序单击数字键“2”,则为按学号排序
单击数字键“3”,则为按房号排序单击数字键“4”,则为按姓名查找
单击数字键“5”,则为按学号查找单击数字键“6”,则为按学号查找
单击数字键“7”,则为按学号插入单击数字键“8”,则为按学号删除
系统中有如下关键词:
提示:
当输入的数字键为0时,退出操作;
请输入数字键(1~8为操作键);
请按任意键进入主界面。
3.2测试数据
3.2.1开始录入的数据:
姓名学号房间号
孟欣201101210
沈学发201102211
陈法威201103212
3.2.2插入的数据:
姓名学号房间号
陈建维201104205
3.2.3查找的数据:
沈学发(按姓名)201104(按学号)211(按房间号)
3.2.4删除的数据:
201102按学号)
3.2.5退出(数字为零时退出):
3.3分析结果
①为了避免繁琐、改进算法,在一些函数中调用了其它的函数。
如:
在按(姓名、学号、房号)查找中都调用了panduan1(ch)和panduan2(ch)函数。
②在插入和删除模块中,显示学生的信息的下面总是有主界面,经过调试,运用system("cls")函数清屏后,显示的只有学生的信息了,再按键即可返回主界面。
③本程序多次运用了disp()、menu()、system("cls")、fflush(stdin)等函数,经过多次调试,已经很好的控制了显示的学生信息与主界面的转换。
4、总结
通过本次数据结构课程设计,我学到了很多,我充分利用了这一周的时间,认真、独立的完成了作业。
我觉得很满足,也很有成就感,许多曾经自己不知道的知识,现在知道了并能熟练的掌握了一些,比如:
(1)一个函数既能调用它本身也能调用其它函数;
(2)如fflush(stdin)函数,它的功能是清空输入缓冲区,得到正确的输入数据;如system("cls")函数,它的功能是将屏幕先前显示的内容清理掉
(3)我以前不知道scanf()和gets()输入函数的不同之处,通过编程,调试,我明白了当scanf()输入字符串时不能带空格,否则不能输出后面的字符,而gets()能输入带空格的字符串。
在编程与调试过程中我遇到了许多问题,具体问题如下:
(1)以前不知道怎么把各个函数编排在一起,不能形成一个总体模块,现在经过实践与调试,已经能组装好各个函数模块,使它们实现各自的功能。
(2)在按关键字(姓名、学号、房号)查找中,由于题目限制了只能用二分查找方式进行查找,所以有时出现了关键字相同时(列如房号相同),就只能查出并显示出一个学生的信息,因此,本程序还不够完善。
当使用顺序查找时,就能查找出所用关键字相同的学生的信息。
当然,当既按姓名又按学号还按房号查找时那就查找唯一。
(3)按(姓名、学号、房号)排序和查找功能每个函数都写了一遍,很繁琐。
C++中的函数模板能解决这个问题,但对于C++我还是个初学者,现在还不懂得如何去运用它,所以还不能对此程序作进一步修改,但我相信,不用多久,这个问题我一定能够解决。
众所周知,要学好编程方面这一块,数据结构是必可少的,它里面有许多经典的算法和思想,是解决问题的必需品。
很惭愧,虽然经过一学期的学习,但我掌握的知识很少,特别是树和图,只知道皮毛,目前还不能用这两方面的知识编程。
在本系统中,我运用了数据结构中的线性表知识,运用顺序线性表完成了宿舍管理查询软件。
在这次课程设计中,经过自己的编成和调试、老师和同学的帮助,我成功的完成了这次作业,虽然它的功能还不是很多,也不是很完善,但我还是非常的兴奋,因为,它给我增添了编程方面的信心,使我更有信心去努力成为一个强力的程序员。
二、纸牌游戏
1、问题分析和任务定义
1.题目:
纸牌游戏
2.要求和任务:
①该题目的要求如下:
(1)将52张牌编号。
(2)从2开始,依次作为基数对基数的倍数的牌进行翻转,直到以52为基数的翻转。
(3)最后输出正面向上的牌。
②基本任务为:
(1)按照要求翻转纸牌。
(2)输出最后正面向上的纸牌的编号。
3.原始数据的输入及输出格式:
原始数据要求输入纸牌的基础编号,编号的输入为整型。
输出的是经过规律翻转后正面向上的纸牌的编号。
输入的数据信息如下:
纸牌:
1、2、3……、51、52。
问题直观分析表:
1
2
3
4
5
6
7
8
9
10
11
12
……
1
2
√
√
√
√
√
√
3
√
√
√
√
4
√
√
√
5
√
√
6
√
√
7
√
8
√
9
√
10
√
11
√
12
√
……
……
(注:
图中“√”表示翻转一次。
)
2.数据结构的选择和概要设计
1.数据结构
按照题目要求,整个主体包括一个嵌套的循环,外循环控制从2开始每张纸牌都作为基数进行翻牌,内循环控制对所有纸牌进行判断,如果是当前循环中基数的倍数,则对其进行翻转操作。
具体代码如下:
for(i=2;i<=52;i++)
{
for(j=1;j<=52;j++)
{
if(j%i==0)
data[j-1]=data[j-1]*Flag;
}
}
2.概要设计
按照题目的要求,首先,应对52张牌进行编号并且保存它们的编号信息,编号的类型为整型,而对于这样固定的数据,使用整型数组是最好的,因此,我们需要在程序的开始定义一共整型的数组,同时,为了方便对翻转过程的记录,在定义记录编号信息的同时,定义一个与之相对应的标记数组,数组类型为整型。
该程序的核心为一个嵌套的循环,所以定义两个变量i,j作为循环条件。
接着开始对变量进行初始化,首先是编号信息数组,使用for循环对数组进行1到52的赋值,代表52张纸牌,然后对标记数组赋值,将数组内的所有的值初始化为零,方便在接下来的循环中统计每张牌的翻牌数。
数据初始化结束后,开始按照要求对纸牌进行翻转,在嵌套循环中,定义了一个全局变量Flag,值为-1,负数定义为向下,正数定义为向上,这样,翻转一次,即乘以Flag,同时,符合翻转条件时,标记数组相应的编号的纸牌翻牌次数+1。
循环结束后,编号数组中的数据已经更新,因此对数组进行扫描,大于零的即为正面向上的纸牌,输出其编号即可,同时,输出标记数组中的值,显示每张牌的翻牌记录,方便观察或者寻找规律。
到此,整个题目结束。
3.详细设计和编码
1.定义全局变量:
作为判断纸牌是否向上的依据,我们需要定义一个全局变量Flag=-1,在循环中对所有纸牌进行操作。
2.主要程序代码与分析如下:
#defineFlag-1
(考虑到最后要判断哪些纸牌是正面向上的,所以必须要有一共判断条件,因此定义一个全局变量作为正反面的判断条件。
)
voidmain()
{
inti,j,data[52],flag[52];
charm;
(在程序开始,建立了两个数组,一个存放52张牌的编号,另外一个存放相应编号的纸牌的翻牌记录,便于后面对翻牌次数的输出。
)
for(i=1;i<=52;i++)
{
data[i-1]=i;
(通过for循环,向数组中录入1-52个数,作为52张牌的编号,以便进行接下来的操作)
flag[i-1]=0;
(将flag数组中的相应编号纸牌的翻牌数初始化为0,在接下来的循环中,需要对翻牌次数进行统计。
)
}
for(i=2;i<=52;i++)
(嵌套循环的外循环,保证基数的循环。
)
{
for(j=1;j<=52;j++)
(嵌套循环的内循环,对每张纸牌进行基数的倍数条件判断)
{
if(j%i==0)
{
data[j-1]=data[j-1]*Flag;
flag[j-1]++;
(翻牌一次,则相应的标记数组中该编号的位置数值+1,即将翻牌次数记入flag数组中。
)
}
}
}
printf("最后所有正面向上的牌有:
");
for(i=0;i<52;i++)
{
if(data[i]>0)
(该题目中将大于零的编号定义为正面向上的纸牌的编号)
printf("第%d张牌",i+1);
}
printf("\n");
}
以上为程序主要代码的分析。
在程序中,主要还包括功能界面,如下:
printf("\t-----------------------------------------------------------\n");printf("\t-----------------------------------------------------------\n");
printf("\t---------欢迎进入纸牌游戏-----------\n");
printf("\t---------1.查看题目-----------\n");
printf("\t---------2.查看所有纸牌的翻牌次数-----------\n");
printf("\t---------3.查看指定编号纸牌翻牌记录-----------\n");
printf("\t---------4.查看最终正面向上的纸牌编号-----------\n");
printf("\t---------5.制作人信息-----------\n");
printf("\t---------0.按0键结束-----------\n");
printf("\t-----------------------------------------------------------\n");
printf("\t-----------------------------------------------------------\n");
同时,整个功能实现由do-while语句和switch语句组合而成,do-while语句可以保证界面最少运行一次,switch语句保证每个功能独立实现,通过choice的输入来进入不同的功能,同时在每个小的独立功能内,我都添加了独立判断是否回到主菜单的语句,如下:
printf("是否回到主菜单?
(Y/N):
");
n=getchar();
n=getchar();
if(n=='Y')break;
elseif(n=='N')
choice=0;
elseprintf("***************(提示:
输入错误,默认为继续。
)***********\n");
整个do-while语句的结束条件为:
choice=0,所以如果用户输入为N,则直接将0赋值给choice,则符合循环结束的条件,则直接结束程序,如果输入为Y,则break,继续循环,输入错误,没有对choice任何的赋值操作,即不能满足结束条件,则无论输入什么都默认为继续,break后继续循环。
由于程序默认的将回车操作通过getchar()赋值给n,导致不能正常的实现下面的判断,而直接显示为输入错误,所以加入两个n=getchar()语句,保证第二句能够正确的实现功能,让用户自行输入条件,进行下一步的操作。
在整个程序中,存在着大量的输入判断条件,如下:
if(num<1&&num>52)
printf("\t输入错误!
\n");
这两句代码就是对输入的num值进行判断,由于纸牌序号为1-52,所以不在这个范围的值都为错误值,需要有一个错误信息的反馈,所以需要对输入的信息进行判断,然后通过不同的值对数据进行相应的操作,这对于程序的正确运行,有着至关重要的作用。
4.上机调试过程
该程序任务相对比较简单,思路较明确。
在一开始编写代码的时候,在嵌套循环中,外循环for的条件(i=2;i<=52;i++),写成(i=1;i<=52;i++),导致对每个纸牌的翻转都多判断了一次,按照一开始定义的大于零的编号数为正面向上的条件,最后输出的结果正好相反,经过修改调试后,问题解决。
在每个case中加入独立的判断是否回到主菜单的语句,一开始getchar()总是不能正确录入,没有输入就直接运行下一个语句,在加入控制语句后经过调试发现,程序把上一个输入的回车直接默认赋值给getchar(),导致没有输入,直接进行下一个语句,后来使用了两个连续的getchar()语句,第一个getchar()语句默认为回车,但是后面一个getchar()语句可以正确的重新输入判断值,经过重新的调试,运行正常,问题解决,但是希望能找到更完善的答案。
在判断是否继续输入纸牌编码的功能中,同样遇到了这个问题,按照相同的解决办法解决。
整个程序由一个大的do-while语句和switch语句组合实现界面的不同功能,do-while语句通过choice=0作为结束的条件,在case3中,有一个小的do-while语句实现纸牌编号的重复输入,在整个程序中有很多信息的输入,需要根据输入的信息正确与否来反馈信息,否则会导致程序出错,所以在调试的过程中加入了很多判断条件,可以解决信息输入错误的情况,但是仍然存在输入非整型值程序出错的问题,所以在输入条件中加入提示信息,以保证信息类型输入正确。
5.测试结果及其分析
1.测试结果如下图1-12;
2结果分析以注释的形式写在图的下方;
(图1)
(注:
MessageBox制作的一个欢迎提示)
(图2)
(注:
纸牌游戏程序的主功能界面。
)
(图3)
(注:
纸牌游戏程序功能1:
查看题目。
)
(图4)
(注:
纸牌游戏程序功能2:
查看所有纸牌的翻牌次数。
)
(图4续1)
(图5)
(注:
纸牌游戏程序功能3:
查看指定编号纸牌翻牌记录。
)
(图8)
(注:
纸牌游戏程序功能4:
查看最终正面向上的纸牌编号。
)
(注:
纸牌游戏程序功能3:
查看指定编号纸牌翻牌记录。
)
(图10)
(注:
纸牌游戏程序结束画面。
)
(图11)
(注:
主界面输入错误提示。
)
(图12)
(注:
功能3输入错误提示以及判断是否需要继续查询纸牌编码。
)
(图13)
(注:
回主菜单判断以及输入错误提示。
)
(图14)
(注:
功能3继续查询纸牌编码判断输入错误提示以及回主菜单输入错误提示。
)
三、猴子吃桃
1.任务描述
猴子吃桃问题涉及一个比较有趣的数组,把猴子吃桃的天数倒过来看的话,以天数作为数组的下标i,剩下桃子的个数a[i]的递推公式为a[i]=(a[i-1]+1)*2。
a[i]实际代表了倒数第i天剩下的桃子数。
所以可以求得此数组的通项公式为a[i]=3*pow(2,(i-1))-2(i>=2)
2.需求分析
这个课程设计分为四个部分,即分别用四种不同的方法解决猴子吃桃子问题。
每个部分都有不同的算法思想。
用数组结构实现的算法,通过构造求桃子数的数组,然后输出要求的项来实现。
用链结构实现的算法,则是建立链表,将每天的桃子数目存入链表,然后输出第一天的桃子数。
用递归结构实现的算法,是通过函数本身的特点,反复调用自身,最后找到递归的出口,求得算法的解。
用数学计算方法,即通过直接利用循环计算,算出猴子第一天的桃子数。
3.本设计所采用的数据结构
二叉树及二叉链表
4.概要设计
如果用数组结构解决这个问题,把猴子吃桃的天数倒过来看的话,以天数作为数组的下标i,剩下桃子的个数a[i]的递推公式为a[i]=(a[i-1]+1)*2。
a[i]实际代表了倒数第i天剩下的桃子数。
所以可以求得此数组的通项公式为a[i]=3*2e(i-1)-2(i>=2)。
如果用链结构解决这个问题,建立一个链表,根据每天桃子数与后一天桃子数的关系n=2*n+2,依次将每天的桃子数存进链表中,最后输出第一天的桃子数。
如果用递归结构解决这个问题,要求利用他们每天都吃当前桃子的一半且再多吃一个这一特点,设计一个递归算法。
如果用数学计算方法解决这个问题,建立一个循环结构,根据其中的数学关系计算出猴子第一天的桃子数。
5.详细设计
5.1数组实现
把猴子吃桃的天数倒过来看的话,以天数作为数组的下标i,剩下桃子的个数a[i]的递推公式为a[i]=(a[i-1]+1)*2。
a[i]实际代表了倒数第i天剩下的桃子数。
所以可以求得此数组的通项公式为a[i]=3*pow(2,(i-1))-2(i>=2)。
数组结构算法的流程图如图3-1:
voidarray()
{
intday=10;
intsum[10],last=1;
sum[day-1]=last;
day=9;
while(day>0)
{
sum[day-1]=(sum[day]+1)*2;
day--;
}
printf("猴子第一天共摘了%d个桃子\n",sum[0]);
}
5.2链结构
用链结构实现这个算法,其核心是利用链表这种存储结构,将每天的桃子数存储在链表中,在链表中实现数的递推。
首先是建立一个空链表,产生一个头结点,且将头结点的地址赋给L。
然后把每天的桃子数从链表的第一个结点插入链表。
最后第一天的桃子数被最后一个插入链表,成为链表中第一个值。
建立单链表的程序代码如下:
linklist*Initlinklist(linklist*L)
{
L=(linklist*)malloc(sizeof(linklist));
L->next=NULL;
return(L);
}
链表创建部分实现:
linklist*Creatlinklist(linklist*L)
{
inti,j;
linklist*r,*p;
r=L;
j=1;
for(i=0;i<=9;i++)
{
p=(linklist*)malloc(sizeof(linklist));
p->data=j;
p->next=NULL;
r->next=p;
r=r->next;
j=(j+1)*2;
}
return(L);
}
封装整个链表方法实现:
voidlianbiao()/*数据存储方式为链表*/
{
linklist*P=NULL,*u;
inti;
P=Initlinklist(P);
Creatlinklist(P);
u=P->next;
for(i=0;i<9;i++)
{
u=u->next;
}
printf("猴子第一天共摘了%d个桃子\n",u->data);
}
5.3递归
设计递归算法,利用x=2*x+2,定义一个函数sum_fan,然后不断调用自身,求得第一天的桃子数。
递归算法的流程图如图3-3
N
Y
主要代码如下:
//此部分定义递归实现
intsum_fan(intn,inti)
{
if(i>0)
{
n=sum_fan((n+1)*2,--i);
}
returnn;
}
voiddigui()/*封装递归实现*/
{
intsum;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构课程设计报告第九组 数据结构 课程设计 报告 第九