《学生成绩管理系统.doc》由会员分享,可在线阅读,更多相关《学生成绩管理系统.doc(106页珍藏版)》请在三一办公上搜索。
1、数据结构课程设计学生姓名: 班 号: 学 号: 指导教师: 实习题目一 学生成绩管理系统【需求规格说明】学生成绩管理是高等学校教务管理的重要组成部分,主要包括学生注册、考试成绩的录入及修改、成绩的统计分析等等。设计一个系统实现对学生成绩的管理。 【基本要求】要求系统应具有以下基本功能:(1)学生注册登记;(2)增加、删除某一班级的学生数;(3)成绩录入:输入学生的考试成绩;(4)成绩修改:若输入错误可进行修改;(5)统计分析:对某个班级学生的单科成绩进行统计,求出平均成绩;求出成绩处于指定分数段内的学生人数;求出每个学生一学期各科的平均成绩等;(6)查找:查找某个学生的某门课程成绩,查找某门课
2、程成绩处于指定分数段内的学生名单等等。(7)打印:打印一个班级学生的单科成绩;打印某一课程成绩处于指定分数段内的学生名单;打印学生在某一学期的成绩报告单;(8)排序:按照学生成绩的总分排序学生记录。【算法设计】(1)设计思想: 本题的核心操作是查询,因为哈希表的查找效率很高,应此在实现该系统的时候考虑到应用哈希表这样一种数据结构. 哈希函数的设计采用除留余数法,解决碰撞冲突采用线性探测在散列的方法。另外考虑到要排序,而且为了实现排序算法的时间复杂度尽可能低,采用了二叉排序树的数据结构解决排序问题。由于哈希表的关键字项只能有一项,为了实现按学号或按姓名查找和按班级插入和删除学生信息,设计了三个哈
3、希表来实现该学生管理系统,其中学号哈希表存放所有的学生信息,包括学号.姓名.班号.C语言成绩.数学成绩.英语成绩.总分以及平均分,其中学号哈希表的表项关键字为学号;姓名哈希表以学生姓名的ASCII码值为表项关键字,其中该姓名哈希表存放了学生的学号作为索引项;班级哈希表以班号为表项关键字,该班级哈希表用一个数组存放了该班所有学生的学号。二叉排序树以学生成绩的总分作为关键字项,另外存放了学生的学号与姓名作为索引信息,排序时,将学生的学号,姓名和总分依次插入二叉排序树,按照成绩总分排序只要中序遍历此二叉树便可得到。实现按学号和按姓名查找,并且实现三个表的动态的修改即(插入和删除),当插入(删除)学生
4、信息到学号哈希表时,先到学号哈希表去查找学生的相关信息,未找到时(找到时)就在学号哈希表中插入(删除)该学生的所有信息,同时也要把学生的信息反映到姓名哈希表和班级哈希表中。当从姓名哈希表插入(删除)学生信息时,计算该学生姓名的ASCII码值作为关键字到姓名哈希表中时,到哈希表中去对应信息,如果找不到(找到)就在姓名哈希表中插入(删除)姓名的ASCII码关键字的值,同时在姓名哈希表中插入(删除)该学生的学号。当从班级哈希表中插入(删除)学生信息时,把班号作为关键字到班级哈希表中去查找对应的信息,如果找不到就提示不存在该班级,找到该班号就在班号哈希表的班级数组中插入该学生的学号,增加该班级的学生人
5、数。 三个哈希表及二叉树之间的对应关系见下图: 学号哈希表关键字项 数据项学号 班号 姓 名 其它信息2006 0010 huang2007 0008 kai 2008 0002 tao2009 0003 liu2010 0004 zhang2011 0009 li2012 0002 wang2013 0006 chen2014 0008 wen2015 0007 yang2016 0006 song2017 0008 jiang2018 0005 xu2019 0006 ren2020 0010 hu。 。 。 。 。2006 0007 lai2007 0006 lei2008 0004 l
6、ong2009 0002 jun2010 0001 xun2011 0003 mei2012 0001 ling2013 0002 ri2014201820102016201720182040210422052030203120342108210922042307240821402036姓名哈希表关键字 学号zhang 2025wang 2027yang 2030song 2031kai 2022huang 2021wen 2029。 。ren 2034lai 2014jiang 2032xun 2018班号哈希表班编号0005000800020010。00030006 0001 0007 二
7、叉排序树关键字 数据项总分 学号 姓名256 2006 lai258 2009 jun260 2012 wang267 2013 ri268 2011 mei269 2010 xun。 。 。280 2015 yang(2)数据结构设计:/*学号哈希表*/typedef structDataType number;/学号char name10;/姓名int classnumber;/班号int cgrade;/语言成绩 int mgrade;/数学成绩int egrade;/英语成绩DataType total;/总分 float ave;/平均分 kindofitem info;/当前状态(
8、是否被访问的标志)Hashitemnum;typedef struct Hashitemnum *ht;/ 学号哈希表数组int tablesize;/表长 int currentsize;/当前表的长度Hashtablenum;/建立的关键字为学号的学号哈希表/*姓名哈希表*/typedef structDataType na;/存放姓名的ascii码的关键字(相当于索引项)int number;/班号kindofitem info;/当前状态Hashitemname;typedef struct Hashitemname *ht;/ 姓名哈希表数组int tablesize; int cu
9、rrentsize;Hashtablename;/建立的关键字为姓名的姓名哈希表/*班级哈希表*/typedef structDataType classnumber;/存放班号的关键字int number50;/存放本班学生学号的数组(相当于索引项)int size;/本班学生的人数kindofitem info; /当前状态Hashitemclassnumber;typedef struct Hashitemclassnumber *ht;/ 班级哈希表数组 int tablesize; int currentsize;Hashtableclassnumber;/建立的关键字为班号的班级哈
10、希表/*二叉排序树的数据结构*/typedef struct tree DataType data;/关键字域int number;/学号char name10;/姓名 struct tree *leftchild;/左孩子 struct tree *rightchild;/右孩子 bitree;/二叉树(3)详细设计说明: 三个哈希表的总体设计:结构体哈希表由哈希表数组,数组个数和当前哈希表项个数三部分组成,其中哈希表数组中每个表项的数据类型是结构体HashItem。结构体HashItem由数据元素和表项状态两部分组成,其中数据元素仅包括一个关键字域,表项状态的数据类型为枚举类型,表项状态有
11、Empty,Active和Deleted三种状态,分别表示表项的空,已占用和被删除三种状态。 数据结构定义如下:哈希表项包括三个,一个是数据元素关键字项,一个是元素的其它信息,还有一个是元素项的当前状态(info).数据元素的当前状态有三种:空,占用(或称活动)和删除,因此,需要定义一个有三个取值Empty,Active和Deleted的枚举类型KindofItem。 存放三个哈希表的数组采用动态数组,初始化时哈希表的表的表长采用总人数的1.5倍。 本题的核心算法是哈希表的插入,查找和删除。其中,插入和删除操作首先需要查找数据元素是否在哈希表中存在。查找函数共有三种情况:查找到,返回数据元素的
12、哈希地址(值为正);未查找到,返回一个负值(插入操作可在哈希表的该返回值的绝对值位置插入数据元素);未找到,且哈希表已满无法插入,此时返回为-tablesize. 插入函数首先调用查找函数,返回值(设为i)为负(说明数据原素不存在)且返回值不等于- tablesize(说明哈希表未满)时,在哈希表的-i位置插入数据元素。【函数模块】create(Hashitemnum*num,int &m,DataType a,int b)Initiatenum(Hashtablenum*hash,int msize)Initiatenumber(Hashtableclassnumber*hash,int m
13、size)Findnum(Hashtablenum *hash,DataType x)Insertnum(Hashtablenum *hash,Hashitemnum*num)Findname(Hashtablename *hash,char p)Deletenum(Hashtablenum *hashnum,DataType x,Hashtablename *hashname)Insertname(Hashtablename *hash,char p,int number)Deletename(Hashtablename *hashname,char *p,Hashtablenum *has
14、hnum,int&m)Findnumber(Hashtableclassnumber *hash,DataType x)Insertclassnumber(Hashtableclassnumber *hash,Hashtablenum *hashnum,DataType x,int b)Deletenumber(Hashtableclassnumber *hash,int i,int number)Add(Hashtableclassnumber *hashnumber, Hashtablenum *hashnum,Hashtablename *hashname)Deletebynum(Has
15、htableclassnumber*hashnumber,Hashtablenum*hashnum,Hashtablename*hashname);Deletebyname(Hashtableclassnumber *hashnumber, Hashtablenum *hashnum,Hashtablename *hashname)Delete(Hashtableclassnumber *hashnumber, Hashtablenum *hashnum,Hashtablename *hashname)xiugai(Hashtablenum *hashnum,Hashtablename *ha
16、shname)Tongji(Hashtableclassnumber *hashnumber,Hashtablenum *hashnum,Hashtablename *hashname)chazhao(Hashtableclassnumber*hashnumber,Hashtablenum*hashnum,Hashtablename*hashname,Hashitemnum*num,int m)print(Hashtableclassnumber*hashnumber,Hashtablenum*hashnum,Hashtablename*hashname,Hashitemnum*num)pri
17、ntmidan(Hashtablenum *hashnum,int b,int&h)insert(bitree *root,Hashitemnum item)Traverse(bitree*root)程序执行中函数调用关系和流程如下:学生信息的登记与成绩录入 完成对三个表的创建增加学生记录删除学生记录修改学生记录Create()Add()Delete()xiugai()统计学生记录查找学生记录打印学生记录排序学生记录tongji()chazhao()print()Paixu()Initiatenum()Initiatename()Initiatenumber()Insertnum ()Inse
18、rtname ()Insertclassnumber()( ()Insertnum () ; Insertname ();Insertclassnumber();Deletebynum(); Deletebyname()Findnumber();Findnum();Findnumber()Deletenumber()Deletename()Deletenum()Findnumber();Findnum()Findname();Findnum();insert(bitree*root,Hashitemnm item)Traverse(bitree*root)【测试数据】 *欢迎使用学生成绩管理系
19、统* 菜 单* * a 学生登记注册与学生成绩录入 b 增加某一班的学生记录 * * c 删除某一班的学生记录 d 修改学生成绩 * * e 统计学生记录 f 查找学生记录 * * g 打印学生记录 h 排序学生记录 * * j 退出 * *请输入全校学生的班级个数:25请输入您要进行的操作:a请输入学生的信息:学生的学号:2008学生的姓名:huang该学生所在的班号:1学生的数学成绩:84学生的英语成绩:85学生的C语言成绩:86继续输入?(Y/N)Y学生的学号:2006学生的姓名:lei该学生所在的班号:1学生的数学成绩:85学生的英语成绩:86学生的C语言成绩:87继续输入?(Y/N)
20、Y学生的学号:2010学生的姓名:kai该学生所在的班号:2学生的数学成绩:84学生的英语成绩:85学生的C语言成绩:96继续输入?(Y/N)Y学生的学号:2012学生的姓名:wei该学生所在的班号:2学生的数学成绩:84学生的英语成绩:85学生的C语言成绩:87继续输入?(Y/N)N学生的信息正在被录入之中.请稍后请输入您要进行的操作:1请输入您要进行的操作:2040请输入您要进行的操作:you请输入您要进行的操作:b请输入您要增加的学生的所在班级的班号:1请输入您要增加的学生的学号:2040请输入您要增加的学生姓名:you学生的数学成绩:88学生的英语成绩:84学生的C语言成绩:85该学生
21、已成功增加到信息系统中!继续输入?(Y/N)N请输入您要进行的操作:c按学号删除 0按姓名删除 1请选择删除方式0/1:0请输入您要删除的学生的所在班级的班号:1请输入您要删除的学生的学号:2008该学生已被成功删除!请输入您要进行的操作:d按姓名修改 0按学号修改 1请选择修改方式:0请输入要修改的学生的姓名:you请输入您要修改的学生的某一项的成绩:修改数学成绩 0修改英语成绩 1修改C语言成绩 2请选择修改方式:0请修改后的数学成绩:99修改成功!请输入您要进行的操作:e请输入您要统计的学生的所在班级的班号:1统计数学成绩 0统计英语成绩 1统计C语言成绩 2请输入您要统计哪一项的成绩:
22、0请输入您要查询的统计的分数段maxmin:请输入max的值:99请输入min的值:68NO.1学生的平均成绩是92.00处于9968之间的学生人数是:2请输入您要进行的操作:f按姓名查找 0按学号查找 1请选择查找方式:0请输入要查找的学生的姓名:you查找数学成绩 0查找英语成绩 1查找C语言成绩 2请选择查找方式:0该学生的数学成绩的是:99查找指定的分数段的数学成绩 0查找指定的分数段的英语成绩 1查找指定的分数段的C语言成绩 2请选择查找方式:0请输入您要查询的数学成绩指定的分数段max1min1请输入max1的值:99请输入min1的值:68成绩指定的分数段9968的学生名单是:k
23、aiyouleiwei请输入您要进行的操作:g请输入您要打印的学生的所在班级的班号:1请输入您要打印哪一项的成绩:打印数学成绩 0打印英语成绩 1打印C语言成绩 2请选择打印方式:0学号 姓名 数学2006 lei 852040 you 99学号 姓名 数学 英语 C语言2010 kai 84 85 962040 you 99 84 852006 lei 85 86 872012 wei 84 85 87请输入您要进行的操作:h2012 wei 2562006 lei 2582010 kai 2652040 you 268请输入您要进行的操作:jPress any key to continu
24、e【调试报告】1、开始时,增加学生记录时可以增加成功,但是到后来在查询的时候却显示该学生记录不存在,设置断点调试后,发现查找函数的状态记录不正确,修改后实现了查找成功。2、在打印学生的姓名时开始打印出来的姓名是乱码,后来调试进行跟踪发现字符串末尾没有添加结束符号0,添加后打印成功。 3、用二叉排序树对学生信息进行排序时发现,总分必须作为关键字项,因此又将学号哈希表的总分项改成了DataType类型,成功将问题解决。【用户手册】根据提示输入相应的学生信息即可,可以任意输入班级个数,学生人数和添加与删除学生信息。【附录】代码清单:#include stdio.h#include stdlib.h#
25、include string.htypedef int keytype;#define Max 1000;typedef enum Empty, Active, Deleted kindofitem;typedef structkeytype key;DataType;typedef structDataType number;char name10;int classnumber;int cgrade; int mgrade; int egrade; DataType total; float ave; kindofitem info;Hashitemnum;typedef structDa
26、taType na;char name10;int number;kindofitem info;Hashitemname;typedef structDataType classnumber;int number50;int size;kindofitem info;Hashitemclassnumber;typedef struct Hashitemnum *ht; int tablesize; int currentsize;Hashtablenum;typedef struct Hashitemname *ht; int tablesize; int currentsize;Hasht
27、ablename;typedef struct Hashitemclassnumber *ht; int tablesize; int currentsize; Hashtableclassnumber;typedef struct tree DataType data;int number;char name10; struct tree *leftchild; struct tree *rightchild; bitree; void create(Hashitemnum*num,int &m,DataType a,int b)int i=0;char flag=y; printf(n请输
28、入学生的信息:n); while(flag=y|flag=Y) printf(学生的学号:); scanf(%d,&numi.number.key); bi=numi.number.key; printf(学生的姓名:); scanf(%s,numi.name); printf(该学生所在的班号:); scanf(%d,&numi.classnumber); ai.key=numi.classnumber; printf(学生的数学成绩:); scanf(%d,&numi.mgrade); printf(学生的英语成绩:); scanf(%d,&numi.egrade); printf(学生的
29、C语言成绩:); scanf(%d,&numi.cgrade); i+; printf(继续输入?(Y/N); scanf(%s,&flag); m=i;void copy(char p,char q)int i=0;while(1)qi=pi; if(pi=0) break;elsei+; int Initiatenum(Hashtablenum*hash,int msize)hash-tablesize=msize;hash-ht=(Hashitemnum*)malloc(sizeof(Hashitemnum)*msize);if(hash-ht=NULL)return 0 ;elseha
30、sh-currentsize=0;return 1;int Initiatename(Hashtablename*hash,int msize)hash-tablesize=msize;hash-ht=(Hashitemname*)malloc(sizeof(Hashitemname)*msize);if(hash-ht=NULL)return 0 ;elsehash-currentsize=0;return 1;int Initiatenumber(Hashtableclassnumber*hash,int msize) hash-tablesize=msize;hash-ht=(Hashi
31、temclassnumber*)malloc(sizeof(Hashitemclassnumber)*msize);if(hash-ht=NULL)return 0 ;elsehash-currentsize=0;return 1;int Findnum(Hashtablenum *hash,DataType x)int i=x.key%hash-tablesize;int j=i;while(hash-htj.info=Active&hash-htj.number.key!=x.key)j=(j+1)%hash-tablesize;if(j=i)return -hash-tablesize;
32、if(hash-htj.info=Active)return j;else return -j;int Insertnum(Hashtablenum *hash,Hashitemnum*num)int i=Findnum(hash,num-number);if(i0)return 0;else if(i!=-hash-tablesize)hash-ht-i.number=num-number; copy(num-name,hash-ht-i.name); hash-ht-i.classnumber=num-classnumber; hash-ht-i.mgrade=num-mgrade; ha
33、sh-ht-i.egrade=num-egrade;hash-ht-i.cgrade=num-cgrade;hash-ht-i.info=Active;hash-currentsize+;return 1;else return 0;int Findname(Hashtablename *hash,char p) DataType x;x.key=0;int k=0;while(1) x.key+=(int)(pk); k+; if(pk=0) break; int i=x.key%hash-tablesize;int j=i;while(hash-htj.info=Active&hash-h
34、tj.na.key!=x.key)j=(j+1)%hash-tablesize;if(j=i)return -hash-tablesize;if(hash-htj.info=Active)return j;else return -j;int Findname1(Hashtablename *hash,char p) DataType x;x.key=0;int k=0;while(1) x.key+=(int)(pk); k+; if(pk=0) break; int i=x.key%hash-tablesize;int j=i;while(hash-htj.na.key!=x.key)j=
35、(j+1)%hash-tablesize;if(j=i)return -hash-tablesize;if(hash-htj.info=Active)return j;else return -j;int Deletenum(Hashtablenum *hashnum,DataType x,Hashtablename *hashname) int i=Findnum(hashnum,x); if(i=0) int j=Findname(hashname,hashnum-hti.name);if(j=0) hashname-htj.info=Deleted; hashname-currentsi
36、ze-; hashnum-hti.info=Deleted;hashnum-currentsize-;return 1;else return 0;int Insertname(Hashtablename *hash,char p,int number)DataType x;x.key=0;int j=0;while(1) x.key+=(int)(pj); j+; if(pj=0) break; int i=Findname(hash,p);if(i0)return 0;else if(i!=-hash-tablesize)hash-ht-i.na=x; hash-ht-i.number=n
37、umber;hash-ht-i.info=Active;hash-currentsize+;return 1;else return 0;int Deletename(Hashtablename *hashname,char *p,Hashtablenum *hashnum,int&m)int i=Findname(hashname,p);if(i=0)DataType x;x.key=hashname-hti.number;x.key=m;int j=Findnum(hashnum,x);if(j=0) hashnum-htj.info=Deleted; hashnum-currentsiz
38、e-;hashname-hti.info=Deleted;hashname-currentsize-;return 1;else return 0;int Findnumber(Hashtableclassnumber *hash,DataType x)int i=x.key%hash-tablesize;int j=i;while(hash-htj.info=Active&hash-htj.classnumber.key!=x.key)j=(j+1)%hash-tablesize;if(j=i)return -hash-tablesize;if(hash-htj.info=Active)return j;else return -j;int Insertclassnumber(Hashtableclassnumber *hash,Hashtablenum *hashnum,DataType x,int b)int j=0,k=0,m;DataType y;int i=Findnumber(hash,x);if(i0)return 0;else if(i!=-hash-tablesize) hash-ht-i.classnumber=x; for(j=0;bj!=-1;j+) y.key=bj; m=Findnum(hashnum,y); if(