课程设计.docx

上传人:b****7 文档编号:10273210 上传时间:2023-02-09 格式:DOCX 页数:23 大小:98.66KB
下载 相关 举报
课程设计.docx_第1页
第1页 / 共23页
课程设计.docx_第2页
第2页 / 共23页
课程设计.docx_第3页
第3页 / 共23页
课程设计.docx_第4页
第4页 / 共23页
课程设计.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

课程设计.docx

《课程设计.docx》由会员分享,可在线阅读,更多相关《课程设计.docx(23页珍藏版)》请在冰豆网上搜索。

课程设计.docx

课程设计

摘要

排序算法是数据结构这门课程核心内容之一,它是计算机程序设计、数据库、操作系统、编译原理级人工智能等的重要基础,广泛的应用于信息学、系统工程等各种领域。

学习排序算法是为了将实际问题中涉及的对象在计算机中对它们进处理。

我们将利用vc++6.0开发程序对各种算法进行测试。

该测试系统可以通过操作吧数据结构中的主要排序常见的排序算法(直接插入排序、希尔排序、直接选择排序、冒泡排序、快速排序、堆排序、归并排序)的性能用时间的长短表现出来。

【关键字】:

数据结构vc++6.0排序算法时间长短

一、任务描述

使用简单数组实现下面各种排序算法,并进行比较。

1、插入排序

2、希尔排序

3、冒泡排序

4、快速排序

5、简单选择排序

1.要求:

1、测试数据分成三类:

正序、逆序、随机数据

2、对于这三类数据,比较上述排序算法中关键字的比较次数和移动次数(其中关键字交换计为3次移动)。

3、对于这三类数据,比较上述排序算法中不同算法的执行时间,精确到微秒(选作)

4、对2和3的结果进行分析,验证上述各种算法的时间复杂度

编写测试main()函数测试线性表的正确性。

 

二、程序分析

 

图2-1程序分析

(1)设计一个菜单,格式如下:

1、直接插入排序2、希尔排序3、冒泡排序4、快速排序

5、选择排序6、堆排序7、退出

(2)选择不同的菜单但进行相应的排序,并给出排序的关键字序列。

三、存储结构关键算法分析

本程序包含了9个函数,它们分别是:

1.直接插入排序的算法函数InsertSort()。

voidInsertSort(SqList&L)

{

inti,j;

for(i=2;i<=L.length;i++)

{

if(L.r[i].key

{

L.r[0]=L.r[i];

L.r[i]=L.r[i-1];

for(j=i-2;(L.r[0].key

L.r[j+1]=L.r[0];

}

}

}

2.希尔排序的算法函数ShellSort()。

voidShellSort(SqList&L)

{

inti,j;

intdk=1;//增量

while(dk<=L.length/3)

dk=3*dk+1;//增大增量

while(dk>0)

{

dk/=3;//减小增量

for(i=dk;i<=L.length;i++){

L.r[0].key=L.r[i].key;

j=i;

while((j>=dk)&&(L.r[j-dk].key>L.r[0].key)){

L.r[j].key=L.r[j-dk].key;

j-=dk;

}

L.r[j].key=L.r[0].key;

}

}

}

3.冒泡排序算法函数BubbleSort()。

voidBubbleSort(SqList&L)

{

inti,j;

for(i=0;i

{

intflag=1;

for(j=0;j

if(L.r[j].key>L.r[j+1].key)

{

flag=0;

inttemp;

temp=L.r[j].key;

L.r[j].key=L.r[j+1].key;

L.r[j+1].key=temp;

}

//若无交换说明已经有序

if(flag==1)

break;

}}

4.快速排序的算法函数Partition()。

voidBubbleSort(SqList&L)

{

inti,j;

for(i=0;i

{

intflag=1;

for(j=0;j

if(L.r[j].key>L.r[j+1].key)

{

flag=0;

inttemp;

temp=L.r[j].key;

L.r[j].key=L.r[j+1].key;

L.r[j+1].key=temp;

}

//若无交换说明已经有序

if(flag==1)

break;

}}

5.选择排序算法函数SelectSort()。

voidSelectSort(SqList&L)

{

intmin;

intj;

for(inti=0;i

{//选择第i小的记录,并交换

j=i;

min=L.r[i].key;

for(intk=i;k

{//在R[i..n-1]中选择最小的记录

if(L.r[k].key

{

min=L.r[k].key;

j=k;

}

}

if(i!

=j)

{//与第i个记录交换

inttemp=L.r[i].key;

L.r[i].key=L.r[j].key;

L.r[j].key=temp;

}

}

}

6.堆排序算法函数HeapAdjust()。

voidHeapAdjust(HeapType&H,ints,intm)

//堆调整,将记录调整为小顶堆intj;

RedTyperc=H.r[s];//暂时存储根结点

for(j=2*s;j<=m;j*=2)

{

//沿着结点记录较小的向下筛选

if(j

++j;

if(rc.key>=H.r[j].key)

break;

H.r[s]=H.r[j];

s=j;

}

H.r[s]=rc;

}

voidHeapSort(HeapType&H)

{

inti;

RedTypetemp;

for(i=H.length;i>0;--i)

HeapAdjust(H,i,H.length);

for(i=H.length;i>1;--i)

{

temp=H.r[1];

H.r[1]=H.r[i];

H.r[i]=temp;

HeapAdjust(H,1,i-1);

}

7.对存储数字的遍历函数

voidVisit(SqListL)

{

for(inti=1;i<=L.length;i++)

cout<

cout<

}

voidInitSqList(SqList&L,inta[])

{

for(inti=1;i<=L.length;i++)

L.r[i].key=a[i];

}

8.主函数main()。

关键算法的时间、空间复杂度:

排序法 平均时间   最差情形      稳定度     额外空间     备注

冒泡    O(n2)            O(n2)            稳定        O

(1)          n小时较好

交换    O(n2)            O(n2)            不稳定     O

(1)            n小时较好

选择    O(n2)            O(n2)            不稳定     O

(1)           n小时较好

插入    O(n2)           O(n2)              稳定       O

(1)           大部分已排序时较好

Shell   O(nlogn)      O(ns)1

(1)        s是所选分组

快速   O(nlogn)        O(n2)             不稳定      O(nlogn)      n大时较好

归并    O(nlogn)      O(nlogn)       稳定        O

(1)           n大时较好

堆      O(nlogn)     O(nlogn)       不稳定   O

(1)           n大时较好

四、主函数流程:

图4-1主函数流程

五、程序运行结果

1.正序输入

图5-1正序输入

2.反序输入

图5-2反序输入

3.随机输入

图5-3随机输入

参考文献

[1]数据结构(C语言版)高等教育出版社胡学纲编著

[2]数据结构与算法高等教育出版社许卓群、杨东青编著

[3]新编考研辅导丛书数据结构辅导西安电子科技大学出版社王卫东编著

[4]数据结构人民邮电出版社刘遵仁编著

[5]数据结构(C语言版)导教、导学、导考西北工业大学出版社姚群、夏清国编著

[6]数据结构(C语言描述)清华大学出版社徐孝凯、贺桂英编著

[7]数据结构(C语言描述)学习指导与习题解析清华大学出版社徐孝凯、贺桂英编著

[8]数据结构(含实训)东南大学出版社齐景嘉编著

[9]数据结构红旗出版社张曼、朱小谷等编著

[10]数据结构习题解析清华大学出版社李春葆编著

[11]数据结构常见题型解析与模拟题西北工业大学出版社朱儒荣、朱辉编著

[12]数据结构习题集与解题指导科学技术文献出版社薛晓燕、王晓冬编著

[13]数据结构(C语言描述)清华大学出版社徐孝凯、贺桂英编著

附录(程序清单)

#include

#include

#include

usingnamespacestd;

inti,j,temp,k;//设置全局变量

longdoubleGetNowTime()//取系统时间

{

LARGE_INTEGERlitmp;

LONG64QPart;

QueryPerformanceCounter(&litmp);

QPart=litmp.QuadPart;

return(longdouble)QPart;

}

 

//插入排序

voidInsertSort(intr[],intn)

{intmove=0,compare=0;

longdoublestart=0,end=0,time=0;

start=GetNowTime();

for(i=2;i

{

if(r[i]

{compare++;

r[0]=r[i];//设置哨兵,存放待排序记录值

for(j=i-1;r[0]

r[j+1]=r[j];//比r[0]大的往后移

r[j+1]=r[0];//插入指定记录值

move=move+3;//关键码的交换按3次记

compare++;

}

}

end=GetNowTime();

time=end-start;

for(k=1;k

cout<

cout<

cout<<"排序所需时间:

"<

"<

"<

cout<

}

//希尔排序

voidShellSort(intr[],intn)

{

intmove=0,compare=0;

longdoublestart=0,end=0,time=0;

start=start=GetNowTime();

intd;//定义增量

for(d=n/2;d>=1;d=d/2)//以增量为d进行直接插入排序

{

for(i=d+1;i

{

compare++;

r[0]=r[i];//设置哨兵,暂存被插入记录

for(j=i-d;j>0&&r[0]

r[j+d]=r[j];//记录后移d个位置

r[j+d]=r[0];//插入指定记录值

move=move+3;

compare++;

}

}

end=GetNowTime();

time=end-start;

for(i=1;i

cout<

cout<

cout<<"排序所需时间:

"<

"<

"<

cout<

}

//改进型起泡排序

voidBubbleSort(intr[],intn)

{

longdoublestart=0,end=0,time=0;

intmove=0,compare=0;

intexchange;

intbound;

exchange=n-1;//第一趟起泡排序的范围是r[0]到r[n-1]

start=GetNowTime();

while(exchange)//仅当上一趟排序有记录交换才进行本趟排序

{

bound=exchange;//表示无序的范围

exchange=0;

for(intj=0;j

if(r[j]>r[j+1])

{

temp=r[j];//交换r[i]和r[i+1]

r[j]=r[j+1];

r[j+1]=temp;

move=move+3;

exchange=j;//记录每一次发生记录交换的位置,即记录无序区的位置

}

compare++;

}

end=GetNowTime();

time=end-start;

for(inti=0;i

cout<

cout<

cout<<"排序所需时间:

"<

"<

"<

cout<

}

//快速排序一次划分

intEmove=0,Ecompare=0;

longdoubleEtime;

intPartition(intr[],intfirst,intend)

{

i=first;//初始化

j=end;

while(i

{

while(i

{Ecompare++;j--;}//右侧扫描

Ecompare++;

if(i

{

temp=r[i];//将较小记录交换到前面

r[i]=r[j];

r[j]=temp;

Emove=Emove+3;

/*i++;*/

}

while(i

{Ecompare++;i++;}//左侧扫描,小于轴值的不移动,找到大于轴值的

Ecompare++;

if(i

{

temp=r[j];

r[j]=r[i];

r[i]=temp;//将较大记录交换到后面

Emove=Emove+3;

/*j--;*/

}

}

 

returni;//i为轴值记录的最终位置

}

//快速排序,在一次排序结束后,左边区的元素都比右边区的小,只要分开再排序即可

voidQuickSort(intr[],intfirst,intend2)

{

longdoublestart=0,end=0;

start=GetNowTime();

if(first

{//递归结束

intpivot=Partition(r,first,end2);//一次划分

QuickSort(r,first,pivot-1);//递归地对左侧子序列进行快速排序

QuickSort(r,pivot+1,end2);//递归地对右侧子序列进行快速排序

}

end=GetNowTime();

Etime=end-start;

}

voidPrint()

{

cout<

"<

"<

"<

}

//简单选择排序,每一趟都找到最小值与比较域内第一个值交换

voidSelectSort(intr[],intn)

{

longdoublestart=0,end=0,time=0;

intcompare=0,move=0;

intindex;//设置关键值下标

start=GetNowTime();

for(i=0;i

{

index=i;

for(j=i+1;j

if(r[j]

index=j;//更新关键值记录

if(index!

=i)//若第一个是最小值就不用交换

{

temp=r[i];

r[i]=r[index];

r[index]=temp;//交换r[i]和关键值记录

move=move+3;

}

compare++;

}

end=GetNowTime();

time=end-start;

for(i=0;i

cout<

cout<

"<

"<

"<

cout<

}

//对数列进行排序

voidpx(intr[],intnumv)

{

cout<<"\n直接顺序排序结果为:

";

InsertSort(r,numv);

cout<<"希尔排序结果为:

";

ShellSort(r,numv);

cout<<"起泡排序结果为:

";

BubbleSort(r,numv-1);

cout<<"快速排序结果为:

";

QuickSort(r,0,numv-1);

for(inti=0;i

cout<

Print();

Emove=0;Ecompare=0;

cout<<"\n";

cout<<"简单选择排序结果为:

";

SelectSort(r,numv-1);

}

//主函数

intmain()

{

constintnumv=11;

inta[numv]={0};

intb[numv]={0};

intc[numv]={0};//初始化

cout<<"请输入10位正整数."<

cout<<"第一组,正序输入a[]=";

try

{

for(i=1;i

cin>>a[i];//从键盘输入待排序记录值

}

catch(char*wrong)

{

cout<

}

px(a,numv);//调用排序函数

cout<<"\n第二组,反序输入b[]=";

try

{

for(i=1;i

cin>>b[i];//从键盘输入待排序记录值

}

catch(char*wrong)

{

cout<

}

px(b,numv);//调用排序函数

cout<<"\n第三组,随机输入c[]=";

try

{

for(i=1;i

cin>>c[i];//从键盘输入待排序记录值

}

catch(char*wrong)

{

cout<

}

px(c,numv);//调用排序函数

return0;

}

在初期构思代码的时候,首先构造了各种算法的基本实现代码,封装成类,已经能够实现七种排序的基本功能,并且测试无误。

后来考虑能否优化本程序,首先考虑到测试算法的需求,需要大量随机数,因为增添了随机函数发生器,满足各种测试条件的需求。

之后考虑如何能简化代码以实现多达七种排序算法的简单调用、乱序和顺序以及逆序数据的分别排序和性能指标统计、算法时间的精确而简易的统计、算法移动次数和比较次数的精确统计。

如果设计不合理,将使得主调函数的调用代码冗长,可读性变差。

因而采用了函数指针数组和统一的接口函数,采用二维数组存储移动次数和比较次数,调用精确的系统函数实现时间的统计。

此外还添加了一些列优化,特别是函数封装的方法,使得程序的结构变得更加合理,版面风格也变得好看,可读性增强。

程序的优化是一个艰辛的过程,如果只是实现一般的功能,将变得容易很多,当加上优化,不论是效率还是结构优化,都需要精心设计。

这次做优化的过程中,遇到不少阻力。

由于优化中用到很多类的封装和访问控制方面的知识,而这部分知识恰好是大一一年学习的薄弱点。

因而以后要多花力气学习C++编程语言,必须要加强这方面的训练,这样才能在将编程思想和数据结构转换为代码的时候能得心应手。

改进:

本程序代码设计时运用了递归的调用方式,效率还可以通过将其转换为栈模拟的方式得以提高。

在实现类的封装的时候为了共享数据采用了友元函数的方式,考虑能否使用其他方式使得类的封装更加完善。

指导教师评语:

 

指导教师(签字):

      年月日

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1