排序综合实验报告.docx

上传人:b****5 文档编号:4814337 上传时间:2022-12-09 格式:DOCX 页数:16 大小:37.43KB
下载 相关 举报
排序综合实验报告.docx_第1页
第1页 / 共16页
排序综合实验报告.docx_第2页
第2页 / 共16页
排序综合实验报告.docx_第3页
第3页 / 共16页
排序综合实验报告.docx_第4页
第4页 / 共16页
排序综合实验报告.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

排序综合实验报告.docx

《排序综合实验报告.docx》由会员分享,可在线阅读,更多相关《排序综合实验报告.docx(16页珍藏版)》请在冰豆网上搜索。

排序综合实验报告.docx

排序综合实验报告

 

 

数据结构

排序算法综合实验报告

 

姓名:

xxxx

班级:

10电信1

学号:

xxx

指导老师:

胡圣荣

日期:

2012.12.15~2013.1.5

 

华南农业大学工程学院

 

算法基本思想:

1、插入排序:

每次将一个待排序的记录,按其关键字大小插入到前面已经排序好的序列中的适当位置,直到全部记录插入完毕为止。

(1)直接插入排序:

在排序过程中,每次都讲无序区中第一条记录插入到有序区中适当位置,使其仍保持有序。

初始时,取第一条记录为有序区,其他记录为无序区。

显然,随着排序过程的进行,有序区不断扩大,无序区不断缩小。

最终无序区变为空,有序区中包含了所有的记录,排序结束。

(2)希尔排序:

将排序表分成若干组,所有相隔为某个“增量”的记录为一组,在各组内进行直接插入排序;初始时增量d1较大,分组较多(每组的记录数少),以后增量逐渐减少,分组减少(每组的记录数增多),直到最后增量为1(d1>d2>...>dt=1),所有记录放为一组,再整体进行一次直接插入排序。

2、交换排序:

每次比较两个待排序的记录,如果发现他们关键字的次序与排序要求相反时就交换两者的位置,直到没有反序的记录为止。

(1)冒泡排序:

设想排序表R[1]到R[n]垂直放置,将每个记录R[i]看作是重量为R[i].key的气泡;根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡违反本原则的轻气泡,就使其向上“漂浮”,如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。

(2)快速排序:

在待排序的n个记录中任取一个作为“基准”,将其与记录分为两组,第一组中个记录的键值均小于或等于基准的键值,第二组中个记录的键值均大于或等于基准的键值,而基准就排在这两组中间(这也是该记录的最终位置),这称为一趟快速排序(或一次划分)。

对所分成的两组重复上述方法,直到所有记录都排在适当位置为止。

3、选择排序:

每次从待排序的记录中选出关键字最小(或最大)的记录,顺序放在已排好序的子序列的后面(或最前),直到全部记录排序完毕。

(1)直接选择排序:

首先,所有记录组成初始无序区R[1]到R[n],从中选出键值最小的记录,与无序区第一个记录R[1]交换;新的无序区为R[2]到R[n],从中再选出键值最小的记录,与无序区第一个记录R[2]交换;类似,第i趟排序时R[1]到R[i-1]是有序区,无序区为R[i]到R[n],从中选出键值最小的记录,将它与无序区第一个记录R[i]交换,R[1]到R[i]变为新的有序区。

因为每趟排序都使有序区中增加一个记录,所以,进行n-1趟排序后,整个排序表就全部有序了。

(2)堆排序:

利用小根堆(或大根堆)来选取当前无序区中关键字最小(或最大)的记录来实现排序的。

下面介绍利用大根堆来排序。

首先,将初始无序区调整为一个大根堆,输出关键字最大的堆顶记录后,将剩下的n-1个记录在重建为堆,于是便得到次小值。

如此反复执行,知道全部元素输出完,从而得到一个有序序列。

4、并归排序:

指将若干个已排序的子表合成一个有序表。

(1)二路并归排序:

开始时,将排序表R[1]到R[n]看成n个长度为1的有序子表,把这些子表两两并归,便得到n/2个有序的子表(当n为奇数时,并归后仍是有一个长度为1的子表);然后,再把这n/2个有序的子表两两并归,如此反复,直到最后得到一个程度为n的有序表为止。

各种排序实验结果:

 

 

CPU

(英特尔)Intel(R)Core(TM)i5CPUM480@2.67GHz

姓名

 xx

内存

4.00GB(金士顿PC3-10600DDR31333MHz)

学号

 xxxxxxxxxx

主板

宏碁JE40_CP

班级

 10电信1班

操作系统

MicrosoftWindows7旗舰版(64位/ServicePack1)

电话

 xxxxxxxxxxxxx

编译软件

VisualC++6.0

email

 609803959@

 

 

10^4

2*10^4

10^5

2*10^5

10^6

2*10^6

10^7

2*10^7

10^8

10^5

正序

逆序

直接插入

(带监视哨)

C

24.874

100.158

2500.3

9995.6

0.099999

5000.05

t(时间)

0.156

0.546

13.391

53.417

>5min

0

27.486

直接插入

(无监视哨)

C

24.874

100.158

2500.3

9995.6

 

0.099999

4999.95

t

0.156

0.578

14.21

56.715

>5min

0

29.137

希尔排序

(无监视哨)

C

0.261664

0.598651

4.29106

9.60946

70.5165

166.929

1084.56

2461.37

17159.6

1.50001

2.24458

t

0.015

0.016

0.047

0.109

0.717

1.591

11.544

27.735

208.722

0.02

0.02

直接选择

C

0

0

0

0

0

0

t

0.218

0.78

19.367

77.32

>5min

19.751

20.249

冒泡(上升)

C

49.9905

199.985

4999.94

19999.9

0.099999

4999.95

t

0.452

1.825

45.542

182.678

>5min

0

47.326

冒泡(下沉)

C

49.9904

199.96

4999.78

19999.9

0.099999

4999.95

t

0.483

1.902

47.239

189.081

>5min

0

47.503

快速(递归)

C

0.170775

0.361618

2.17042

4.79646

25.8125

57.6668

320.86

647.454

3493.6

2201.3

2201.4

t

0.01

0.01

0.031

0.062

0.219

0.484

2.577

5.297

29.377

18.026

18.195

堆排序

(非递归)

C

0.235479

0.510793

3.01938

6.43895

36.7932

77.5876

434.639

909.281

5012.88

3.11252

2.92664

t

0.016

0.016

0.047

0.094

0.499

0.968

7.223

17.093

123.429

0.04

0.05

堆排序

(递归)

C

0.235479

0.510793

3.01938

6.43895

36.7932

77.5876

434.639

909.281

5012.88

3.11252

2.92664

t

0

0.015

0.078

0.125

0.903

1.825

13.659

31.742

235.346

0.06

0.07

二路归并

(非递归)

C

0.123676

0.267361

1.56651

3.33305

18.7166

39.4319

224.002

468.006

2540.15

0.877986

0.815024

t

0

0.015

0.046

0.062

0.25

0.546

3.017

6.457

35.309

0.03

0.03

 

实验结果原因分析和结论:

1.插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度。

反而在这种情况下,快速排序反而慢了。

当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。

若待排序的记录的关键字在一个明显有限范围内时,且空间允许是用桶排序。

当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。

当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下。

宜用归并排序。

当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序。

2.插入排序、冒泡排序、选择排序的时间复杂性为O(n2)

 其它非线形排序的时间复杂性为O(nlog2n)

 线形排序的时间复杂性为O(n);

 

3.在算法运行期间,运行QQ软件、360安全卫士、360杀毒、word文档、ppt、酷狗等软件会影响绝对时间和逻辑时间,使时间增大

 

4.随着n的取值增大,算法的实际时间增长速度逐渐增大。

 

5.直接插入排序(有、无监视哨)、冒泡排序(上升、下沉)、堆排序(递归、非递归)的关键字比较次数相同,但绝对时间相差比较大;直接选择排序与冒泡排序的关键字比较次数相近。

 

6.相比较其他同学的数据,直接插入(有、无监视哨),直接选择,冒泡(上升、下沉)的结果相差较小,希尔选择结果相差很大,另快速(递归),堆(递归,非递归),二路归并(非递归)结果并不会受计算机环境而不同。

 

附录:

源程序极其代码

#defineCPPC++

#defineMPPM++

#defineMP2M+=2

#defineMP3M+=3

#include

#include

#include

#include

#include

constintmaxsize=20000;//排序表容量

typedefintdatatype;

typedefstruct{

datatypekey;//关键字域

//othertypeother;//其它域

}rectype;//记录类型

typedefrectypelist[maxsize+2];//排序表类型,0号单元不用

__int64C,M;//比较和移动次数

voidcheck(listR,intn){//检验排序结果

inti;

for(i=2;i<=n;i++)

if(R[i].key

\n";return;}

cout<<"Correct!

";

}

voiddisp(listR,intn){//显示排序后的结果

inti;

for(i=1;i<=n;i++){

cout<

//if(i%20==0)cout<

}

cout<

}

voidInsertSort1(listR,intn){//直接插入排序,带监视哨(并不改变关键字次数)

inti,j;

for(i=2;i<=n;i++){//依次插入R[2],R[3],…,R[n]

if(CPP,R[i].key>=R[i-1].key)continue;

//R[i]大于有序区最后一个记录,则本趟不需插入

MPP,R[0]=R[i];//R[0]是监视哨

j=i-1;

do{//查找R[i]的插入位置

MPP,R[j+1]=R[j];j--;//记录后移,继续向前搜索

}while(CPP,R[0].key

MPP,R[j+1]=R[0];//插入R[i]

}

}

voidInsertSort2(listR,intn){//直接插入排序,无监视哨

inti,j;rectypex;//x为辅助量(用R[0]代替时间变长)

for(i=2;i<=n;i++){//进行n-1次插入

if(CPP,R[i].key>=R[i-1].key)continue;

MPP,x=R[i];//待排记录暂存到x

j=i-1;

do{//顺序比较和移动

MPP,R[j+1]=R[j];j--;

}while(j>=1&&(CPP,x.key

MPP,R[j+1]=x;//插入R[i]

}

}

voidShellSort1(listR,intn){//一趟插入排序,h为本趟增量

inth,i,j,k;

for(h=n/2;h>=1;h=h/2){

for(i=1;i<=h;i++){//i为组号

for(j=i+h;j<=n;j+=h){//每组从第2个记录开始插入

if(CPP,R[j].key>=R[j-h].key)continue;//R[j]大于有序区最后一个记录,

//则不需要插入

MPP,R[0]=R[j];//R[0]保存待插入记录,但不是监视哨

k=j-h;//待插记录的前一个记录

do{//查找正确的插入位置

MPP,R[k+h]=R[k];k=k-h;//后移记录,继续向前搜索

}while(k>0&&(CPP,R[0].key

MPP,R[k+h]=R[0];//插入R[j]

}

}

if(h==1)break;

}

}

voidSelectSort1(listR,intn){

inti,j,k;

for(i=1;i<=n-1;i++){//n-1趟排序

k=i;

for(j=i+1;j<=n;j++)//在当前无序区从前向后找键值最小的记录R[k]

if(R[j].key

if(k!

=i){R[0]=R[i];R[i]=R[k];R[k]=R[0];}//交换R[i]和R[0],R[0]作辅助量

}

}

 

voidBubbleSort1(listR,intn){//上升法冒泡排序

inti,j,flag;rectypex;//x为辅助量(可用R[0]代替)

for(i=1;i<=n-1;i++){//做n-1趟扫描

flag=0;//置未交换标志

for(j=n;j>=i+1;j--)//从下向上扫描

if(CPP,R[j].key

flag=1;

MP3,x=R[j];R[j]=R[j-1];R[j-1]=x;//交换

}

if(!

flag)break;//本趟未交换过记录,排序结束

}

}

voidBubbleSort2(listR,intn){//下沉法,冒泡排序

inti,j,flag;rectypex;//x为辅助量(可用R[0]代替)

for(i=1;i<=n-1;i++){//做n-1趟扫描

flag=0;//置未交换标志

for(j=1;j<=n-i;j++)//从上向下扫描

if(CPP,R[j].key>R[j+1].key){//交换记录

flag=1;

MP3,x=R[j];R[j]=R[j+1];R[j+1]=x;//交换

}

if(!

flag)break;//本趟未交换过记录,排序结束

}

}

intPartition(listR,intp,intq){//对R[p]到R[q]划分,返回基准位置

inti,j;rectypex;//辅助量(可用R[0]代替)

i=p;j=q;MPP,x=R[p];//x存基准(无序区第一个记录)

do{

while((CPP,R[j].key>=x.key)&&i

if(i

while((CPP,R[i].key<=x.key)&&i

if(i

}while(i

MPP,R[i]=x;//基准移到最终位置

returni;//最后i=j

}

voidQuickSort1(listR,ints,intt){//对R[s]到R[t]快速排序,递归算法m

inti;

if(s>=t)return;//只有一个记录或无记录时无需排序

i=Partition(R,s,t);//对R[s]到R[t]做划分

QuickSort1(R,s,i-1);//递归处理左区间

QuickSort1(R,i+1,t);//递归处理右区间

}

voidSift1(listR,intp,intq){//堆范围为R[p]~R[q],调整R[p]为堆,非递归算法

intj;

MPP,R[0]=R[p];//R[0]作辅助量

j=2*p;//j指向R[p]的左孩子

while(j<=q){

if(j

if(CPP,R[0].key>=R[j].key)break;//根结点键值大于孩子结点,已经是堆,调整结束

MPP,R[p]=R[j];//将R[j]换到双亲位置上

p=j;//修改当前被调整结点

j=2*p;//j指向R[p]的左孩子

}

MPP,R[p]=R[0];//原根结点放入正确位置

}

voidSift2(listR,intp,intq){//堆范围为R[p]~R[q],调整R[p]为堆,递归算法

intj;

if(p>=q)return;//只有一个元素或无元素

j=2*p;

if(j>q)return;

if(j

if(CPP,R[p].key>=R[j].key)return;//根结点关键字已最大

MPP,R[0]=R[j];//交换R[j]和R[p],R[0]作辅助量

MPP,R[j]=R[p];

MPP,R[p]=R[0];

Sift2(R,j,q);//递归

}

voidHeadSort1(listR,intn){//堆R[1]到R[n]进行堆排序

inti;

for(i=n/2;i>=1;i--)Sift1(R,i,n);//建初始堆

for(i=n;i>=2;i--){//进行n-1趟堆排序

MPP,R[0]=R[1];//堆顶和当前堆底交换,R[0]作辅助量

MPP,R[1]=R[i];

MPP,R[i]=R[0];

Sift1(R,1,i-1);//R[1]到R[i-1]重建成新堆

}

}

voidHeadSort2(listR,intn){//堆R[1]到R[n]进行堆排序

inti;

for(i=n/2;i>=1;i--)Sift2(R,i,n);//建初始堆

for(i=n;i>=2;i--){//进行n-1趟堆排序

MPP,R[0]=R[1];//堆顶和当前堆底交换,R[0]作辅助量

MPP,R[1]=R[i];

MPP,R[i]=R[0];

Sift2(R,1,i-1);//R[1]到R[i-1]重建成新堆

}

}

voidMerge(listR,listR1,intlow,intmid,inthigh){

//合并R的两个子表:

R[low]~R[mid]、R[mid+1]~R[high],结果在R1中

inti,j,k;

i=low;

j=mid+1;

k=low;

while(i<=mid&&j<=high)

if(CPP,R[i].key<=R[j].key)MPP,R1[k++]=R[i++];//取小者复制

elseMPP,R1[k++]=R[j++];

while(i<=mid)MPP,R1[k++]=R[i++];//复制左子表的剩余记录

while(j<=high)MPP,R1[k++]=R[j++];//复制右子表的剩余记录

}

voidMergePass(listR,listR1,intn,intlen){//对R做一趟归并,结果在R1中

inti,j;

i=1;//i指向第一对子表的起始点

while(i+2*len-1<=n){//归并长度为len的两个子表

Merge(R,R1,i,i+len-1,i+2*len-1);

i=i+2*len;//i指向下一对子表起始点

}

if(i+len-1

Merge(R,R1,i,i+len-1,n);

else//子表个数为奇数,剩一段

for(j=i;j<=n;j++)//将最后一个子表复制到R1中

MPP,R1[j]=R[j];

}

voidMergeSort(listR,listR1,intn){//对R二路归并排序,结果在R中(非递归算法)

intlen;

len=1;

while(len

MergePass(R,R1,n,len);len=len*2;//一趟归并,结果在R1中

MergePass(R1,R,n,len);len=len*2;//再次归并,结果在R中

}

}

intrandom1(intnum){returnrand();}//0~RAND_MAX=32767

intrandom3(intnum){//素数模乘同余法,0~M

intA=16807;//16807,39722040,764261123,63036001648271?

intM=2147483647;//有符号4字节最大素数,2^31-1

intQ=M/A;

intR=M%A;

staticintx=1,n=0,g=0;//seed(setto1)

staticdoubler,r1=0,r2=0;

intx1;

x1=A*(x%Q)-R*(x/Q);

if(x1>=0)x=x1;

elsex=x1+M;

r=1.*x/M;if(r>0.5)g++;

n++;r1+=r;r2+=r*r;

if(n%maxsize==0){

cout<<"x="<

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

当前位置:首页 > 高中教育 > 其它课程

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

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