武汉理工大学数据结构课程设计Word文档格式.docx
《武汉理工大学数据结构课程设计Word文档格式.docx》由会员分享,可在线阅读,更多相关《武汉理工大学数据结构课程设计Word文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
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<
<
"
文件打开失败!
endl;
else
{
head=newelem;
elem*p1=head;
head->
next;
for(inti=0;
fin;
i++)
{
elem*p=newelem;
fin>
>
p->
data;
p->
next=p1->
p1->
next=p;
p2=p1;
p1=p;
}
p2->
next=NULL;
//读入的最后一个数无效,故舍去。
fin.close();
}
}
2.3.2随机数据产生函数
该函数用到的是伪随机数rand(),并由参数n和w限制个数和分布范围。
其实可以把语句fout<
rand()%w<
"
;
改写成fout<
float(rand()%w)/33*31<
这样的形式,获得大致分布在0—w范围内的随机小数。
voidrand_data(intn,intw)
//产生n个分布在0—w范围内的随机数,并写入文件datatxt中
ofstreamfout("
fout)cout<
if(w>
0)
i<
n;
fout<
float(rand()%w)<
elseif(w<
for(inti=0;
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;
//始终指向待排数据的最大(小)值
start=clock();
for(elem*p=head->
p!
=NULL;
p=p->
next)
p2=p;
for(elem*p1=p->
p1!
p1=p1->
if(p2->
data>
p1->
data&
&
cho==0)
p2=p1;
elseif(p2->
data<
cho==1)
temp=p2->
//通过中间变量交换数据,完成一轮排序,筛选出一个最值。
data=p->
p->
data=temp;
end=clock();
cout<
算法用时为"
(double)(end-start)/CLOCKS_PER_SEC<
秒"
endl<
endl;
//计算算法执行时间
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]=='
+j)&
(a[1]=='
\0'
))
return1;
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:
\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<
stdlib.h>
time.h>
iostream>
fstream>
usingnamespacestd;
voidprint(elem*head)
//遍历链表,在屏幕上显示每个结点中的数据
head=head->
while(head!
=NULL)
cout<
head->
head=head->
voidcheck(elem*head,intcho)
//通过对相邻数据大小进行比较,判断排序算法结果是否正确
intflag=1;
if(head)
while(head->
next!
if(head->
next->
{
cout<
你的排序算法有误,因为发现了顺序错误的地方。
flag=0;
break;
}
head=head->
if(flag)
cout<
经过对排序后的数据分析,你的排序结果正确!
voidcreat(elem*&
head)
//数据产生方式人机交互模块
charcho[10],n1[10];
intw,n;
do{
通过系统产生随机数请选择1,自己写入文件请选择0。
cin>
cho;
while(!
ana(cho,1,0));
if(cho[0]=='
1'
系统会自动产生浮点数,请输入数据的个数N和分布范围W(数据分布在0-W区间)。
do
cin>
n>
w;
if(w==0)
范围w值不能为0,请重新输入!
while(w==0);
rand_data(n,w);
creat_self(head);
请把数据写入到data.txt文件中,数据之间以空格间隔。
不要输入字符,否则,字符后的数据将被忽略。
数据输入完成后,输入任意字符继续。
n1;
voidmain()
charcho[10];
system("
colorF0"
//为使输出窗口视觉效果更佳,这里设置背景色为亮白色(F),前景色为黑色(0)。
elem*head=NULL;
=========================================================="
欢迎使用链式选择排序系统!
creat(head);
查看当前(未排序)链表中的数据吗?
查看请选择1,跳过请选择0。
while(!
if(cho[0]=='
print(head);
cout<
请选择排序方式:
从大到小选择1,从小到大选择0。
排序算法运行结果如下:
————————————————————————————————————————"
sort(head,cho[0]-'
print(head);
check(head,cho[0]-'
本科生课程设计成绩评定表
班级:
姓名:
学号:
序号
评分项目
满分
实得分
1
学习态度认真、遵守纪律
10
设计分析合理性
3
设计方案正确性、可行性、创造性
20
4
设计结果正确性
40
5
设计报告的规范性
6
设计验收
总得分/等级
评语:
注:
最终成绩以五级分制记。
优(90-100分)、良(80-89分)、中(70-79分)、
及格(60-69分)、60分以下为不及格
指导教师签名:
201年 月 日