武汉理工大学数据结构课程设计.docx
- 文档编号:7766273
- 上传时间:2023-01-26
- 格式:DOCX
- 页数:20
- 大小:381.55KB
武汉理工大学数据结构课程设计.docx
《武汉理工大学数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《武汉理工大学数据结构课程设计.docx(20页珍藏版)》请在冰豆网上搜索。
武汉理工大学数据结构课程设计
学号:
课程设计
题目
链式简单选择排序
学院
计算机科学与技术学院
专业
班级
姓名
LDSD
指导教师
耿枫
2013
年
7
月
2
日
课程设计任务书
学生姓名:
LDSD专业班级:
指导教师:
耿枫工作单位:
计算机科学与技术学院
题目:
链式简单选择排序
初始条件:
试写一个程序,以单链表作为存储结构,实现简单选择排序。
1、课程设计报告中应有你的算法的时间复杂度分析;
2、测试用例自己设计。
要求完成的主要任务:
(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)
课程设计报告按学校规定格式用A4纸打印(书写),并应包含如下内容:
1、问题描述
简述题目要解决的问题是什么。
2、设计
存储结构设计、主要算法设计(用类C语言或用框图描述)、测试用例设计;
3、调试报告
调试过程中遇到的问题是如何解决的;对设计和编码的讨论和分析。
4、经验和体会(包括对算法改进的设想)
5、附源程序清单和运行结果。
源程序要加注释。
如果题目规定了测试数据,则运行结果要包含这些测试数据和运行输出,
6、设计报告、程序不得相互抄袭和拷贝;若有雷同,则所有雷同者成绩均为0分。
时间安排:
1、第20周(6月29日至7月3日)完成。
2、7月3日8:
00到计算中心检查程序、交课程设计报告、源程序(CD盘)。
指导教师签名:
年月日
系主任(或责任教师)签名:
年月日
链式简单选择排序
链式简单选择排序主要涉及到数据结构中链表和排序两个知识点,其中,链表的知识又涉及创建、插入、遍历等。
为了获得测试用例,还需掌握随机数产生方法以及文本文件读写的相关操作。
所以,课程设计是很考验我们综合能力的,通过学习,可以进一步提升我们的软件开发能力。
1.课程设计问题描述及开发工具
1.1课程设计问题描述
试编写一个程序,以单链表作为存储结构,实现对待排序表中的数据的简单选择排序,用多组测试例子对程序进行测试,并输出排序结果。
1.2开发工具
本课程设计需要安装有支持标准C/C++的VisualC++编译器(VC6.0或更高版本)的计算机一台。
2.程序设计
2.1思想描述
为解决问题,首先要建立一组测试用例,本程序提供两中产生数据的方法,在交互界面下,用户可自行选择。
一种是直接通过计算机利用rand()函数产生随机数并写入文件;另一种则是由用户自己向文件中输入数据。
其次要建立一个单链表,将该文件中的数据(设置为float类型)逐个存储在建立的单链表中。
最后,依次对单链表中的结点数据进行简单选择排序,其中排序分为从大到小排序和从小到大排序两种方式,同样可在交互界面下,由用户自行选择。
排序后,输出排序结果和运行时间,为保证结果正确性,还要做对结果进行检查。
整个人机交互过程中,为保证用户输入指令的合法性,还要对输入数据进行词法分析。
选择排序基本思想是:
通过n-i次关键字比较,从n-i+1(i=1,2,...,n-1)个记录中选取关键字最大或最小的记录作为有序序列中第i个记录。
以此方法循环下去,直到排序完成。
程序总流程图如上所示
2.2存储结构设计
本课程设计要求使用线性表的链式存储结构来存储待排序的数据,定义一个结点类型,它包括两个域:
存储数据元素信息的数据域,存储后继元素地址的指针域。
单链表结构体的定义如下:
structelem
{
floatdata;
elem*next;
};
值域data以float型存储所要排序的数据,指针域next以指针型存储了指向下一个结点的地址。
2.3主要算法设计
本程序中的几个较为核心的算法有:
创建链表函数voidcreat_self(elem*&head),随机数函数voidrand_data(intn,intw),简单选择排序voidsort(elem*head,intcho),词法分析函数intana(chara[],inti,intj)。
现依次用c++语言描述他们的具体算法。
2.3.1链表的创建
在文件data.txt中,已经保存了要排序的数据,通过读取文件,可以为每个结点写入数据。
创建的这个单链表是带头结点的,在遍历它的时候当注意这点,一般情况下,文件是可以打开的,但如果文件无法打开,则输出提示信息并退出函数。
voidcreat_self(elem*&head)
//把文件中的数据读出,并建立一个头指针为head的单链表,保存这些数据
{
intc=0;
elem*p2;
ifstreamfin("data.txt");
if(!
fin)cout<<"文件打开失败!
"< else { head=newelem; elem*p1=head; head->next; for(inti=0;fin;i++) { elem*p=newelem; fin>>p->data; p->next=p1->next; p1->next=p; p2=p1; p1=p; } p2->next=NULL;//读入的最后一个数无效,故舍去。 fin.close(); } } 2.3.2随机数据产生函数 该函数用到的是伪随机数rand(),并由参数n和w限制个数和分布范围。 其实可以把语句fout< voidrand_data(intn,intw) //产生n个分布在0—w范围内的随机数,并写入文件datatxt中 { ofstreamfout("data.txt"); if(! fout)cout<<"文件打开失败! "< else { if(w>0) for(inti=0;i { fout< } elseif(w<0) for(inti=0;i { fout<<0-float(rand()%abs(w))<<""; } } fout.close(); } 2.3.3链式简单排序 基本实现思想是: 从链表的当前结点(由p指向)开始依次往下检索,找到在指定结点之后所有结点中最小(最大)的那个结点,把地址保存在p2中,完成一轮循环后,把p2所指向的结点数据与p所指向的结点数据进行交换。 然后使得p=p->next,即进入外层循环,直到循环到最后一个结点为止。 这里还用到了一个函数clock(),它包含在头文件time.h中,用来计算程序的运行时间,有利于我们更直观地了解程序的效率。 函数实现代码如下: voidsort(elem*head,intcho) //选择排序算法,参数cho决定排序方式 { clock_tstart,end; floattemp; elem*p2;//始终指向待排数据的最大(小)值 start=clock(); for(elem*p=head->next;p! =NULL;p=p->next) { p2=p; for(elem*p1=p->next;p1! =NULL;p1=p1->next) { if(p2->data>p1->data&&cho==0) p2=p1; elseif(p2->data p2=p1; } temp=p2->data;//通过中间变量交换数据,完成一轮排序,筛选出一个最值。 p2->data=p->data; p->data=temp; } end=clock(); cout<<"算法用时为"<<(double)(end-start)/CLOCKS_PER_SEC<<"秒"< //计算算法执行时间 } 2.3.4词法分析 在实际输入过程中,用户可能输入非法字符,所以这里需要对数据进行分析,一旦输入不合法,就要提示用户重新输入,否则,本程序可能会崩溃。 a[]保存输入的字符,i,j是程序允许的指令。 基本思想为: 获取用户输入的字符串a[],把a[0]和i,j比较,若比较成功,并且a[1]为‘\0’时,返回1,否则,返回0。 intana(chara[],inti,intj) //词法分析,检验用户的输入是否合法 { if((a[0]=='0'+i||a[0]=='0'+j)&&(a[1]=='\0')) return1; else return0; } 3.程序调试过程问题与改正 在本课程设计的程序调试过程中,出现错误提示如下: (1)--------------------Configuration: test-Win32Debug-------------------- Compiling... test.cpp E: \c++安装\MyProjects\课设\test.cpp(17): errorC2628: 'elem'followedby'void'isillegal(didyouforgeta';'? ) 执行cl.exe时出错. 分析: 原来,在定义完结构体以后,没有在括号外面打上“,”,结构体的定义与函数体的格式有点相似,但是函数体后面不用加“,”,这些都是细节上的东西,不要把二者混淆了。 (2)有一次的调试结果如图所示: 分析: 可以看出,本来是要由计算机自动产生3个随机数,结果链表保存了4个数,并且第四个数明显是错误的。 通过分析文件读写过程,发现最后一次保存到链表的数据实际上是无效的。 通过改正creat_self(elem*&head)函数,即删除链表最后一个结点,问题解决。 (3)--------------------Configuration: test-Win32Debug-------------------- Compiling... test.cpp E: \c++安装\MyProjects\课设\test.cpp(113): errorC2065: 'flag': undeclaredidentifier 执行cl.exe时出错。 分析: 在voidcheck(elem*head,intcho)函数中,定义了一个flag变量,用于标示运行状态,但却提示flag未定义,原来,flag被定义在了while语句中,走出while语句后,就不在其作用域内里。 把flag定义在函数开头位置,问题解决。 4.运行结果及说明 4.1以随机方式创建链表 输入n为100,分布范围w为200,产生100个随机数,建立一个链表。 输出的结果如下: 4.2用户自己写入数据 用户把数据手动输入到文件data.txt中。 4.3比较三组不同输入数据的排序 (1)3000个数据从小到大排序结果如下: (2)500个数据从小到大的排序结果: (3)2000个数据从大到小排序结果如下: 4.4结果分析 (1)这里使用的数据也可以是小数,负数,但字符等是不允许的。 (2)在voidcreat(elem*&head)函数中,head必须是一个指针的引用,否则,通过函数建立的链表头指针无法传递。 (3)用例一是产生3000个分布在0—4444间的随机数,并按照从小到大的顺序排序,可以看到,用时为0.047秒,排序后的数据经过check(elem*head)函数的检查,结果正确。 用例二是对500组负数排序,因为数据较少,故用时极短,系统显示的用时为0秒。 用例三是对2000组分布在0—6666范围的数据排序,用时0.031秒。 对同样一组数据而言,排序的时间可能不同,但差距都很小。 5.时间复杂度分析 链式简单选择排序voidsort(elem*head,intcho)时间复杂度为o(n*n);随机数产生函数voidrand_data(intn,intw),创建函数,检查函数voidcheck(elem*head,intcho),打印函数voidprint(elem*head)时间复杂度均为o(n)。 6.经验与体会 省略 7.课程设计源程序 /* 链式简单选择排序程序 武汉理工大学 LDSD 2013年7月2日 */ #include #include #include #include usingnamespacestd; structelem { floatdata; elem*next; }; voidrand_data(intn,intw) //产生n个分布在0—w范围内的随机数,并写入文件datatxt中 { ofstreamfout("data.txt"); if(! fout)cout<<"文件打开失败! "< else { if(w>0) for(inti=0;i { fout< } elseif(w<0) for(inti=0;i { fout<<0-float(rand()%abs(w))<<""; } } fout.close(); } intana(chara[],inti,intj) //词法分析,检验用户的输入是否合法 { if((a[0]=='0'+i||a[0]=='0'+j)&&(a[1]=='\0')) return1; else return0; } voidcreat_self(elem*&head) //把文件中的数据读出,并建立一个头指针为head的单链表,保存这些数据 { intc=0; elem*p2; ifstreamfin("data.txt"); if(! fin)cout<<"文件打开失败! "< else { head=newelem; elem*p1=head; head->next; for(inti=0;fin;i++) { elem*p=newelem; fin>>p->data; p->next=p1->next; p1->next=p; p2=p1; p1=p; } p2->next=NULL;//读入的最后一个数无效,故舍去。 fin.close(); } } voidprint(elem*head) //遍历链表,在屏幕上显示每个结点中的数据 { head=head->next; while(head! =NULL) { cout< head=head->next; } } voidsort(elem*head,intcho) //选择排序算法,参数cho决定排序方式 { clock_tstart,end; floattemp; elem*p2;//始终指向待排数据的最大(小)值 start=clock(); for(elem*p=head->next;p! =NULL;p=p->next) { p2=p; for(elem*p1=p->next;p1! =NULL;p1=p1->next) { if(p2->data>p1->data&&cho==0) p2=p1; elseif(p2->data p2=p1; } temp=p2->data;//通过中间变量交换数据,完成一轮排序,筛选出一个最值。 p2->data=p->data; p->data=temp; } end=clock(); cout<<"算法用时为"<<(double)(end-start)/CLOCKS_PER_SEC<<"秒"< //计算算法执行时间 } voidcheck(elem*head,intcho) //通过对相邻数据大小进行比较,判断排序算法结果是否正确 { intflag=1; head=head->next; if(head) { while(head->next! =NULL) { if(head->data>head->next->data&&cho==0) { cout<<"你的排序算法有误,因为发现了顺序错误的地方。 "< flag=0; break; } if(head->data { cout<<"你的排序算法有误,因为发现了顺序错误的地方。 "< flag=0; break; } head=head->next; } if(flag) cout<<"经过对排序后的数据分析,你的排序结果正确! "< } } voidcreat(elem*&head) //数据产生方式人机交互模块 { charcho[10],n1[10]; intw,n; do{ cout<<"通过系统产生随机数请选择1,自己写入文件请选择0。 "< cin>>cho; } while(! ana(cho,1,0)); if(cho[0]=='1') { cout<<"系统会自动产生浮点数,请输入数据的个数N和分布范围W(数据分布在0-W区间)。 "< do { cin>>n>>w; if(w==0) cout<<"范围w值不能为0,请重新输入! "< } while(w==0); rand_data(n,w); creat_self(head); } else { cout<<"请把数据写入到data.txt文件中,数据之间以空格间隔。 "< cout<<"不要输入字符,否则,字符后的数据将被忽略。 "; cout< "< cin>>n1; creat_self(head); } } voidmain() { charcho[10]; system("colorF0");//为使输出窗口视觉效果更佳,这里设置背景色为亮白色(F),前景色为黑色(0)。 elem*head=NULL; cout<<"=========================================================="< cout<<"欢迎使用链式选择排序系统! "< cout<<"=========================================================="< creat(head); do { cout<<"查看当前(未排序)链表中的数据吗? 查看请选择1,跳过请选择0。 "< cin>>cho; } while(! ana(cho,1,0)); if(cho[0]=='1') print(head);cout< do { cout<<"请选择排序方式: 从大到小选择1,从小到大选择0。 "< cin>>cho; } while(! ana(cho,1,0)); cout< "< cout<<"————————————————————————————————————————"< sort(head,cho[0]-'0'); print(head); cout< cout<<"————————————————————————————————————————"< check(head,cho[0]-'0'); } 本科生课程设计成绩评定表 班级: 姓名: 学号: 序号 评分项目 满分 实得分 1 学习态度认真、遵守纪律 10 2 设计分析合理性 10 3 设计方案正确性、可行性、创造性 20 4 设计结果正确性 40 5 设计报告的规范性 10 6 设计验收 10 总得分/等级 评语: 注: 最终成绩以五级分制记。 优(90-100分)、良(80-89分)、中(70-79分)、 及格(60-69分)、60分以下为不及格 指导教师签名: 201年 月 日
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 武汉理工大学 数据结构 课程设计