1、数据结构课程设计多关键字排序工学院 计算机工程学院课程设计报告设计名称: 数据结构课程设计 选题名称: 多关键字排序 姓 名: 学 号: 专业班级: 网络工程 081 系 (院): 计算机工程学院 设计时间: 设计地点: 软件工程实验室、教室成绩:指导教师评语:签名: 1 .课程设计目的3. 训练学生灵活应用所学数据结构知识, 独立完成问题分析,结合数据结构理论知识,编写程序求 解指定问题。4.初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;5.提高综合运用所学的理论知识和方法独立分析和解决问题的能力;6.训练用系统的观点和软件开发一般规范进行软件开发,巩固、深化学生
2、的理论知识,提高编程水 平,并在此过程中培养他们严谨的科学态度和良好的工作作风。2.课程设计任务与要求:任务题目:多关键字的排序【问题描述】多关键字的排序有其一定的实用范围。例如:在进行高考分数处理时,除了需对总分进行排序外, 不同的专业对单科分数的要求不同,因此尚需在总分相同的情况下,按用户提出的单科分数的次序要求 排出考生录取的次序。【基本要求】(1) 假设待排序的记录不超过 10000,表中记录的关键字数不超过 5,各个学科关键字的范围均为 0至100,总分关键字的范围是 0-300。按用户给定的进行排序的关键字的优先关系,输出排序结果。(2) 约定按LSD法进行多关键字的排序。在对各个
3、关键字进行排序时采用两种策略:其一是利用 稳定的内部排序法,其二是利用“分配”和“收集”的方法。并综合比较这两种策略。【测试数据】由随机数产生器生成。【实现提示】由于是按LSD方法进行排序,则对每个关键字均可进行整个序列的排序, 但在利用通常的内部排序方法进行排序时,必须选用稳定的排序方法要求:1、 在处理每个题目时,要求从分析题目的需求入手,按设计抽象数据类型、构思算法、通过设计实 现抽象数据类型、编制上机程序和上机调试等若干步骤完成题目,最终写出完整的分析报告。前期准备 工作完备与否直接影响到后序上机调试工作的效率。在程序设计阶段应尽量利用已有的标准函数,加大 代码的重用率。2、 .设计的
4、题目要求达到一定工作量(300行以上代码),并具有一定的深度和难度。3、 程序设计语言推荐使用 C/C+,程序书写规范,源程序需加必要的注释 ;4、 每位同学需提交可独立运行的程序;5、 每位同学需独立提交设计报告书(每人一份) ,要求编排格式统一、规范、内容充实,不少于10页(代码不算);6、 课程设计实践作为培养学生动手能力的一种手段,单独考核 。3.课程设计说明书一需求分析 1)选题功能分析【题目的意义】1、 对高考分数按照总分和不同学科的分数按照优先级顺序排出考生录取的次序,以满足 不同专业对单科分数的要求。2、 对不同排序策略进行综合比较。【实现的功能】1、 用C语言设计实现一个高考
5、成绩排序系统。2、 创建模拟的高考考生成绩表,存放到 txt文档中。考生考号为 1, 2, 3用伪随机数生成器 生成各考号学生的各个学科成绩,并计算总分成绩。3、 由于实际中高考考生成绩表是已知的(模拟创建的 txt文档),程序能从文件中读取数据。 从创建的考生成绩表中读取数据,并对数据处理4、 按照学科的优先级顺序,对学生的成绩排序。既可以以某一学科的单科成绩优先级最高排 序,也可以先按总分优先级最高来排序。5、 在对各个关键字即单科成绩进行排序的时候, 分别用稳定的内部排序法(冒泡法)以及“分 配和搜集”的方法进行排序。6、 能够对冒泡法排序策略和“分配和搜集”方法排序策略进行的执行时间进
6、行比较。7、 输入数据:1各科英文首字母的代号,字符型,如 smce2整型数,0-100001输出程序用两种方法进行排序的进程和执行时间2输出前n名学生的信息二概要设计1、 伪随机生成的数据包含语文、数学、英语三科成绩。总成绩为语文、数学、英语三科成绩的和。学号按成绩数组的下标赋值,生成学生成绩记录,将该记录保存到 txt文档中2、 从上面的txt文档中读取数据到一个二维数组中,以便对学生信息进行处理3、 给出排序的优先关系,根据优先关系由低位向高位逐个关键字进行排序。4、 对单科成绩进行排序的时候,单科成绩虽然是 0-100 ,但总成绩是0-300,所以要建301个队列进行排序,先按“分配”
7、和“搜集”的方法进行一趟“基数排序” ;然后再按照稳定的内部排序法(冒泡法)进行排序。将搜集好的或排序好的序列存储,以进行对次优先级的关键字进行再排序。5、 将排序好的学生成绩按照用户提出的提取人数的要求,保存到另一个 txt文档中,并输出到屏幕6、 系统用到的抽象数据类型定义double BubTime1, /按第一个关键字代表的学科成绩用冒泡法排序执行的时间BubTime2,BubTime3,BubTime4, BubTimeSum, /冒泡法排序的总时间DCTime1, /按第一个关键字代表的学科成绩用分配和收集的方法执行的时间DCTime2,DCTime3, DCTime4.DCTim
8、eSum; 分配和收集法排序的总时间int score100005, /随机创建的模拟学生记录源数组bubble100005, 进行冒泡法排序时用来存放学生记录源数组,并且随排序进行数组中的记录发生交换copy100005; 从模拟的学生记录源txt文件中读取学生记录到该数组struct LSD d301; 分配数组,该处考虑到把总分(0-300)也列入优先级序列中,因此建立了 301个队列int *c10000; 用来存放收集到的学生记录char x5; 存放有优先关系的学科代号序列7、系统中的各个函数模块1: void CreatScore(int score100005);高考中该表是已
9、知的,不必创建2: void Collect(struct LSD d301,int *c10000);分配好的记录收集到 c指针数组保存3: void InitDivide(struct LSD d301);次收集后必须做的工作4: double DCSort(struct LSD d301,int *c10000,int n); 排序的方法5: double BubbleSort(int score100005,int n);6: void Print();出到屏幕上7: void savesources(int score100005,int n);存放到文件中8: void saver
10、esults(int score100005,int n);学生记录),将这n条学生的记录存放到新的文件中9:void load( int score100005);取记录到该二维数组中&各函数之间的调用关系随机创建学生记录表 score。正常/LSD法排序中的收集函数,即将用于初始化临时分配数组,在每分配(Divide )和收集(Collect)冒泡法排序将排序结果文件中的记录数据输将模拟创建的高考学生信息记录/按照用户的要求(总成绩在前多少名的/从学生高考记录源文件中读1:主函数可以调用除子函数 2之外的所有函数2 :子函数4可以调用子函数 2和3【功能模块图】三详细设计1.抽象数据类型:
11、该数据类型是在分配和收集的时候存放分配成绩数组1抽象数据类型struct LSDstruct LSD/队列的结构类型,链表存储结构类型int *cur;当前位置struct LSD *next;/队列中下一个位置;,随机生成语2 CreatScore(int score RecordNumberKeyNumber)函数/*创建一个含有 RecordNumber名学生成绩记录的 score,包含语文、数学、英语、总分和学号 文、数学、英语的成绩。*传递的参数是成绩数组 score,无返回值*/void CreatScore(i nt scoreRecordNumberKeyNumber)/*伪随
12、机生成语文、数学、英语的成绩 */for(i=0;i RecordNumber;i+) for(j=0;j3;j+) scoreij=ra nd()%101; / 成绩的范围是 0-100/*总分成绩初始化*/for(i=0;i RecordNumber;i+)scorei3=scorei0+scorei1+scorei2;/*学号的初始化*/for(i=0;i=0; i-) if(di.cur!=NULL)当前队列不空,即有学生的成绩分配到该队列p=&di; while(p-cur!=NULL) /当前位置有学生的成绩cj=P_cur; j+; p=p-n ext;/收集到C指针数组中/指针
13、p指向该队列的下一个位置4 初始化分配数组 InitDivide(struct LSD dQueueNumber)学生的成绩就是队列号/当前队列为空将cj代表的学生的成绩添加到该队列中/初始化刚刚添加了学生记录的队列/当前队列不为空将cj代表的学生的成绩添加到该队列中/新申请一个空间来存放学生成绩/分配完毕将分配好的成绩序列收集到 c中/初始化分配数组II返回执行时间/*初始化d数组即置空,在每一次收集后必须做的工作*传递的参数是 struct LSD dQueueNumber,无返回值 */ void Ini tDivide(struct LSD dQueueNumber)for(i nt
14、i=O;iQueueNumber;i+)di.cur=NULL;di. next=NULL;5分配和收集方法排序 double DCSort(struct LSD dQueueNumber,int*cRecordNumber,i nt n)/*分配和收集方法排序*分配数组为d,收集数组为c*进行排序的关键字所代表的学科成绩 n在分配数组中的位置就是 n*传递的参数是分配数组 struct LSD dQueueNumber,用来收集的指针数组 int *cRecordNumber,关键字代表的学科在数组中的下标*/double DCSort(struct LSD dQueueNumber,i n
15、t *cRecordNumber,i nt n) /*按关键字代表的学科成绩将成绩分配到 d中*/for(j=0;jcur=NULL;p1- next=NULL;p_n ext=p1;elsep=&dtemp;/*循环,一直到队列的结尾 */while(p-cur!=NULL) p=p-n ext;p-cur=cj;p仁(struct LSD *)malloc(LENGTH); p1-cur=NULL;p1- next=NULL;p_n ext=p1;Collect(d,c);Ini tDivide(d);return time;6冒泡法排序 double BubbleSort(int bub
16、bleR/*冒泡法排序*传递的参数是学生成绩记录 int bubbleRecordNumberKeyNumber,关键字所代表学科成绩在数组中的下标*/double BubbleSort(int bubbleRecordNumberKeyNumber,int n)for(i nt i=0;iRecordNumber;i+)for(i nt j=0;jRecordNumber-1-i;j+)if(bubblej n bubblej+1 n)/*交换学生的各科成绩*/for(i nt m=0;mKeyNumber;m+)temp=bubblejm;bubblejm=bubblej+1m; bubb
17、lej+1m=temp;return time; /返回排序执行的时间返回执行的时间7 Prin t()函数/*从排序结果存放的文件 recordresults.txt中读取记录输出到屏幕上*/void Print()FILE *fp;if(fp=fope n( D:recordresults.txt,rb)=NULL)printf(文件打开失败!n);elseprintf(文件打开成功!n);char t;while(fsca nf(fp,%c, &t) & !feof(fp)if(t!=EOF)prin tf(%c,t); /如果读到结束符,循环结束,输出结束fclose(fp); / 关
18、闭文件8 savesources(int score RecordNumberKeyNumber,int n)/*保存学生记录的函数*参数为要保存的学生记录和记录条数*无返回值*/void savesources(i nt scoreRecordNumberKeyNumber,i nt n)if(fp=fope n( D:recordsources.txt,wb)=NULL) / 只写printf(文件打开失败!n); exit(1);fprin tf(fp,%d, n); /将记录条数写入文件fprin tf(fp,rn); 将换行符号写入文件for(i=0;i n;i+)fprin tf(
19、fp,%10d%-10d%-10d%-10d%-10d, scorei4,scorei0,scorei1,scorei2,scorei3); 格式写入记录fprin tf(fp,r n); 将换行符号写入文件fclose(fp);9 saveresults(int scOReCordNumberKeyNumber,int n)/*保存学生记录的函数*参数为要保存的学生记录和记录条数*无返回值*/指向文件的指针/只写,打开或建立一个二进制文件,只允许将记录条数写入文件将换行符号写入文件void saveresults(i nt scoreRecordNumberKeyNumber,i nt n)
20、 FILE *fp;if(fp=fope n( D:recordresults.txt,wb)=NULL)写数据printf(文件打开失败!n); exit(1);fprin tf(fp,%d, n);fprin tf(fp,rn);for(i=0;i n;i+)fprin tf(fp,%10d%-10d%-10d%-10d%-10d, scorei4,scorei0,scorei1,scorei2,scorei3); 格式写入记录fprin tf(fp,r n); 将换行符号写入文件fclose(fp);10 load(int scoRfcordNumberKeyNumber)/*读入函数,
21、把文件中的记录度入到二维数组中*参数为结构体数组*/void load(i nt scoreRecordNumberKeyNumber)FILE *fp;if(fp=fope n(D:recordsources.txt,rt)=NULL) / 打开文件printf(”文件打开失败!n); exit(1);读入记录数按格式读入记录 fscan f(fp,%d,&n); for(i=0;i n;i+) fscan f(fp,%d %d %d %d %d, &scorei4, &scorei0, &scorei1, &scorei2, &scorei3); fclose(fp);11 算法分析1)L
22、SD算法:这是一种“低位优先”的排序方法,借助一趟基数排序的方法,先按最低位的值 对记录进行初步排序,在此基础上再按次低位的值进行进一步排序。以此类推,有低位到 高位,每一趟都是在前一趟的基础上,根据关键字的某一位对所有的记录进行排序,直至 最高位,这样就完成了基数排序的全过程。从算法中可以看出,对于n个记录(每个记录含d个子关键字,每个子关键字的 取值范围为RADIX个值)进行链式排序的时间复杂度为 0(d(n+RADIX),其中每一趟分配算法 的时间复杂度为0(n),每一趟收集的算法的时间复杂度为 O(RADIX),整个排序进行d趟分 配和收集,所需辅助空间为 2*RADIX个队列指针。由
23、于需要链表作为存储结构,则相对于 其他以顺序结构存储记录的排序方法而言,还增加了 n个指针域的空间。2)冒泡法排序:该排序是比较简单的交换类排序方法,通过相邻数据元素的交换,逐步将带排序 列变成有序序列的过程。最坏情况下,待排序的记录按关键字的逆序进行排列,此时,每一趟冒泡排序需 要进行i次比较,3i次移动。经过n-1趟冒泡排序后,总的比较次数为N=Ei=n(n-1)/2,n=1 , 2,,n-1.总的移动次数为3n(n-1)/2次,因此该算法的时间复杂度为 O(n*n),空间复杂 度为O(1)。另外,冒泡排序法是一种稳定的每部排序法。四测试成果崖序正在模拟创建16000高考成绩记录并保存到文
24、件D: XFecordresDUPces.txt中、 麟畐曦保存成功 _您可以】昂过路栓D: i*ecordsources . txt逬行查看.:.E序系统开始运行* *10000条记录到排序系统中富弩賈要按嗚嬲业舉醪專绩逬行排序比如(总分,数学,悟文,英语)鵜赛曙駅蹩行林比如廊数学语文英涪)耀夢配请稍后本義分配知收集用时:0.AAA s冒追法遼行排序,请稍后本次冒泡连徘序用时;1-344 s请稍后S列在程序正在按s代表的学程a行唸分配,请稍后 夯配完电下面开始进行收矍葡霏收峯完取本次分配和收集用时:0-000 s黯寵麟購翻间九0-032请问您要提取多少条学生的成绩信息(0-10000): 2
25、0郴翳少条学E信息g) =202B2803100?9829?6575?a9898294611?9429Q214675?21002874474988928697979128533238S9?2831030879898283佔砖921008928147119丄9792281翦629G94912816779092992911090958&1002814463998498291L943G7%992QQ4998?41R927948259S?23927933459S8?942?9592394982797755?9992?6Pressany key toinue五附录(源程序清单)#in clude#in
26、clude#in clude#in clude#defi ne LENGTH sizeof(struct LSD)int mai n()double BubTimel,BubTime2,BubTime3,BubTime4, BubTimeSum, DCTimel, DCTime2, DCTime3, DCTime4, DCTimeSum;/按第一个关键字代表的学科成绩用冒泡法排序执行的时间/冒泡法排序的总时间/按第一个关键字代表的学科成绩用分配和收集的方法执行的时间/分配和收集法排序的总时间int score100005,随机创建的模拟学生记录源数组 bubble100005,发生交换/进行冒泡法排序时用来存放学生记录源数组,并且随排序进行数组中的记录copy100005; struct LSD d301; 301个队列 int *c10000; char x5;/从模拟的学生记录源 txt文件中读取学生记录到该数组/分配数组,该处考虑到把总分( 0-300)也列入优先级序列中,因此建立了/用来存放收集到的学生记录/存放有优先关系的学科代号序列/*初始化c,使其与score函数同步*/ for(i nt i=0;i10000;i+)ci=scorei;Ini tDivide(d);/初始化队列/*在实际中全部学生的高考
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1