武汉理工大学数据结构课程设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

学号:
课程设计
题目链式简单选择排序
学院计算机科学与技术学院
专业
班级
姓名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.课程设计问题描述及开发工具........................................... - 4 -
1.1 课程设计问题描述................................................ - 4 -
1.2 开发工具........................................................ - 4 - 2.程序设计............................................................. - 4 -
2.1思想描述......................................................... - 4 -
2.2存储结构设计..................................................... - 6 -
2.3 主要算法设计.................................................... - 6 -
2.3.1 链表的创建................................................. - 6 -
2.3.2随机数据产生函数........................................... - 7 -
2.3.3链式简单排序............................................... - 8 -
2.3.4词法分析................................................... - 9 - 3.程序调试过程问题与改正............................................... - 9 - 4.运行结果及说明...................................................... - 10 -
4.1以随机方式创建链表.............................................. - 10 -
4.2 用户自己写入数据............................................... - 11 -
4.3 比较三组不同输入数据的排序..................................... - 11 - 5.时间复杂度分析...................................................... - 13 - 6.经验与体会.......................................................... - 14 - 7.课程设计源程序...................................................... - 14 -
链式简单选择排序
链式简单选择排序主要涉及到数据结构中链表和排序两个知识点,其中,链表的知识又涉及创建、插入、遍历等。

为了获得测试用例,还需掌握随机数产生方法以及文本文件读写的相关操作。

所以,课程设计是很考验我们综合能力的,通过学习,可以进一步提升我们的软件开发能力。

1.课程设计问题描述及开发工具
1.1 课程设计问题描述
试编写一个程序,以单链表作为存储结构,实现对待排序表中的数据的简单选择排序,用多组测试例子对程序进行测试,并输出排序结果。

1.2 开发工具
本课程设计需要安装有支持标准C/C++的Visual C++编译器(VC6.0或更高版本)的计算机一台。

2.程序设计
2.1思想描述
为解决问题,首先要建立一组测试用例,本程序提供两中产生数据的方法,在交互界面下,用户可自行选择。

一种是直接通过计算机利用rand()函数产生随机数并写入文件;另一种则是由用户自己向文件中输入数据。

其次要建立一个单链表,将该文件中的数据(设置为float类型)逐个存储在建立的单链表中。

最后,依次对单链表中的结点数据进行简单选择排序,其中排序分为从大到小排序和从小到大排序两种方式,同样可在交互界面下,由用户自行选择。

排序后,输出排序结果和运行时间,为保证结果正确性,还要做对结果进行检查。

整个人机交互过程中,为保证用户输入指令的合法性,还要对输入数据进行词法分析。

选择排序基本思想是:通过n-i次关键字比较,从n-i+1(i=1,2,...,n-1)个记录中选取关
键字最大或最小的记录作为有序序列中第i个记录。

以此方法循环下去,直到排序完成。

程序总流程图如上所示
2.2存储结构设计
本课程设计要求使用线性表的链式存储结构来存储待排序的数据,定义一个结点类型,它包括两个域:存储数据元素信息的数据域,存储后继元素地址的指针域。

单链表结构体的定义如下:
struct elem
{
float data;
elem *next;
};
值域data以float型存储所要排序的数据,指针域next以指针型存储了指向下一个结点的地址。

2.3 主要算法设计
本程序中的几个较为核心的算法有:创建链表函数void creat_self(elem *&head),随机数函数void rand_data(int n,int w),简单选择排序void sort(elem *head,int cho),词法分析函数int ana(char a[],int i,int j)。

现依次用c++语言描述他们的具体算法。

2.3.1 链表的创建
在文件data.txt中,已经保存了要排序的数据,通过读取文件,可以为每个结点写入数据。

创建的这个单链表是带头结点的,在遍历它的时候当注意这点,一般情况下,文件是可以打开的,但如果文件无法打开,则输出提示信息并退出函数。

void creat_self(elem *&head)
//把文件中的数据读出,并建立一个头指针为head的单链表,保存这些数据
{
int c=0;
elem *p2;
ifstream fin("data.txt");
if(!fin) cout<<"文件打开失败!"<<endl;
else
{
head=new elem;
elem *p1=head;
head->next;
for(int i=0;fin;i++)
{
elem *p=new elem;
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<< rand()%w<<" ";改写成fout<< float(rand()%w)/33*31<<" ";这样的形式,获得
大致分布在0—w范围内的随机小数。

void rand_data(int n,int w)
//产生n个分布在0—w范围内的随机数,并写入文件datatxt中
{
ofstream fout("data.txt");
if(!fout) cout<<"文件打开失败!"<<endl;
else
{
if(w>0)
for(int i=0;i<n;i++)
{
fout<<float(rand()%w)<<" ";
else if(w<0)
for(int i=0;i<n;i++)
{
fout<<0-float(rand()%abs(w))<<" ";
}
}
fout.close();
}
2.3.3链式简单排序
基本实现思想是:从链表的当前结点(由p指向)开始依次往下检索,找到在指定结点之后所有结点中最小(最大)的那个结点,把地址保存在p2中,完成一轮循环后,把p2所指向的结点数据与p所指向的结点数据进行交换。

然后使得p=p->next,即进入外层循环,直到循环到最后一个结点为止。

这里还用到了一个函数clock(),它包含在头文件time.h中,用来计算程序的运行时间,有利于我们更直观地了解程序的效率。

函数实现代码如下:
void sort(elem *head,int cho)
//选择排序算法,参数cho决定排序方式
{
clock_t start,end;
float temp;
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;
else if(p2->data<p1->data&&cho==1)
p2=p1;
}
temp=p2->data; //通过中间变量交换数据,完成一轮排序,筛选出一个最值。

p2->data=p->data;
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。

int ana(char a[],int i,int j)
//词法分析,检验用户的输入是否合法
{
if((a[0]=='0'+i||a[0]=='0'+j)&&(a[1]=='\0'))
return 1;
else
return 0;
}
3.程序调试过程问题与改正
在本课程设计的程序调试过程中,出现错误提示如下:
(1)--------------------Configuration: test - Win32 Debug--------------------
Compiling...
test.cpp
E:\c++安装\MyProjects\课设\test.cpp(17) : error C2628: 'elem' followed by 'void' is illegal (did you forget a ';'?)
执行cl.exe 时出错.
分析:原来,在定义完结构体以后,没有在括号外面打上“,”,结构体的定义与函数体的格式有点相似,但是函数体后面不用加“,”,这些都是细节上的东西,不要把二者混淆了。

(2)有一次的调试结果如图所示:
分析:可以看出,本来是要由计算机自动产生3个随机数,结果链表保存了4个数,
并且第四个数明显是错误的。

通过分析文件读写过程,发现最后一次保存到链表的数据实
际上是无效的。

通过改正creat_self(elem *&head)函数,即删除链表最后一个结点,问题
解决。

(3)--------------------Configuration: test - Win32 Debug--------------------
Compiling...
test.cpp
E:\c++安装\MyProjects\课设\test.cpp(113) : error C2065: 'flag' : undeclared identifier
执行cl.exe 时出错。

分析:在void check(elem *head,int cho)函数中,定义了一个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)在void creat(elem *&head) 函数中,head必须是一个指针的引用,否则,通过函数建立的链表头指针无法传递。

(3)用例一是产生3000个分布在0—4444间的随机数,并按照从小到大的顺序排序,可以看到,用时为0.047秒,排序后的数据经过check(elem *head)函数的检查,结果正确。

用例二是对500组负数排序,因为数据较少,故用时极短,系统显示的用时为0秒。

用例三是对2000组分布在0—6666范围的数据排序,用时0.031秒。

对同样一组数据而言,排序的时间可能不同,但差距都很小。

5.时间复杂度分析
链式简单选择排序void sort(elem *head,int cho)时间复杂度为o(n*n);随机数产生函数void rand_data(int n,int w),创建函数,检查函数void check(elem *head,int cho),打印函数void print(elem *head)时间复杂度均为o(n)。

6.经验与体会
省略
7.课程设计源程序
/*
链式简单选择排序程序
武汉理工大学
LDSD
2013年7月2日
*/
#include<stdlib.h>
#include<time.h>
#include<iostream>
#include<fstream>
using namespace std;
struct elem
{
float data;
elem *next;
};
void rand_data(int n,int w)
//产生n个分布在0—w范围内的随机数,并写入文件datatxt中{
ofstream fout("data.txt");
if(!fout) cout<<"文件打开失败!"<<endl;
else
{
if(w>0)
for(int i=0;i<n;i++)
{
fout<<float(rand()%w)<<" ";
}
else if(w<0)
for(int i=0;i<n;i++)
{
fout<<0-float(rand()%abs(w))<<" ";
}
}
fout.close();
}
int ana(char a[],int i,int j)
//词法分析,检验用户的输入是否合法
{
if((a[0]=='0'+i||a[0]=='0'+j)&&(a[1]=='\0'))
return 1;
else
return 0;
}
void creat_self(elem *&head)
//把文件中的数据读出,并建立一个头指针为head的单链表,保存这些数据{
int c=0;
elem *p2;
ifstream fin("data.txt");
if(!fin) cout<<"文件打开失败!"<<endl;
else
{
head=new elem;
elem *p1=head;
head->next;
for(int i=0;fin;i++)
{
elem *p=new elem;
fin>>p->data;
p->next=p1->next;
p1->next=p;
p2=p1;
p1=p;
}
p2->next=NULL; //读入的最后一个数无效,故舍去。

fin.close();
}
}
void print(elem *head)
//遍历链表,在屏幕上显示每个结点中的数据
{
head=head->next;
while(head!=NULL)
{
cout<<head->data<<' ';
head=head->next;
}
}
void sort(elem *head,int cho)
//选择排序算法,参数cho决定排序方式
{
clock_t start,end;
float temp;
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;
else if(p2->data<p1->data&&cho==1)
p2=p1;
}
temp=p2->data; //通过中间变量交换数据,完成一轮排序,筛选出一个最值。

p2->data=p->data;
p->data=temp;
}
end=clock();
cout<<"算法用时为"<<(double)(end-start)/CLOCKS_PER_SEC<<"秒"<<endl<<endl ;
//计算算法执行时间
}
void check(elem *head,int cho)
//通过对相邻数据大小进行比较,判断排序算法结果是否正确
{
int flag=1;
head=head->next;
if(head)
{
while(head->next!=NULL)
{
if(head->data>head->next->data&&cho==0)
{
cout<<"你的排序算法有误,因为发现了顺序错误的地方。

"<<endl;
flag=0;
break;
}
if(head->data<head->next->data&&cho==1)
{
cout<<"你的排序算法有误,因为发现了顺序错误的地方。

"<<endl;
flag=0;
break;
}
head=head->next;
}
if(flag)
cout<<"经过对排序后的数据分析,你的排序结果正确!"<<endl;
}
}
void creat(elem *&head)
//数据产生方式人机交互模块
{
char cho[10],n1[10];
int w,n;
do{
cout<<"通过系统产生随机数请选择1,自己写入文件请选择0。

"<<endl;
cin>>cho;
}
while(!ana(cho,1,0));
if(cho[0]=='1')
{
cout<<"系统会自动产生浮点数,请输入数据的个数N和分布范围W(数据分布在0-W区间)。

"<<endl;
do
{
cin>>n>>w;
if(w==0)
cout<<"范围w值不能为0,请重新输入!"<<endl;
}
while(w==0);
rand_data(n,w);
creat_self(head);
}
else
{
cout<<"请把数据写入到data.txt文件中,数据之间以空格间隔。

"<<endl;
cout<<"不要输入字符,否则,字符后的数据将被忽略。

";
cout<<endl<<"数据输入完成后,输入任意字符继续。

"<<endl;
cin>>n1;
creat_self(head);
}
}
void main()
{
char cho[10];
system("color F0"); //为使输出窗口视觉效果更佳,这里设置背景色为亮白色(F),前景色为黑色(0)。

elem *head=NULL;
cout<<"=========================================================="<<endl;
cout<<" 欢迎使用链式选择排序系统!"<<endl;
cout<<"=========================================================="<<endl;
creat(head);
do
{
cout<<"查看当前(未排序)链表中的数据吗?查看请选择1,跳过请选择0。

"<<endl;
cin>>cho;
}
while(!ana(cho,1,0));
if(cho[0]=='1')
print(head);cout<<endl;
do
{
cout<<"请选择排序方式:从大到小选择1,从小到大选择0。

"<<endl;
cin>>cho;
}
while(!ana(cho,1,0));
cout<<endl<<"排序算法运行结果如下:"<<endl;
cout<<"————————————————————————————————————————"<<endl;
sort(head,cho[0]-'0');
print(head);
cout<<endl;
cout<<"————————————————————————————————————————"<<endl;
check(head,cho[0]-'0');
}
武汉理工大学《数据结构》课程设计说明书
本科生课程设计成绩评定表
班级:姓名:学号:
及格(60-69分)、60分以下为不及格
指导教师签名:
201 年月日。

相关文档
最新文档