数据结构排序.docx

上传人:b****1 文档编号:2815532 上传时间:2023-05-04 格式:DOCX 页数:16 大小:23.21KB
下载 相关 举报
数据结构排序.docx_第1页
第1页 / 共16页
数据结构排序.docx_第2页
第2页 / 共16页
数据结构排序.docx_第3页
第3页 / 共16页
数据结构排序.docx_第4页
第4页 / 共16页
数据结构排序.docx_第5页
第5页 / 共16页
数据结构排序.docx_第6页
第6页 / 共16页
数据结构排序.docx_第7页
第7页 / 共16页
数据结构排序.docx_第8页
第8页 / 共16页
数据结构排序.docx_第9页
第9页 / 共16页
数据结构排序.docx_第10页
第10页 / 共16页
数据结构排序.docx_第11页
第11页 / 共16页
数据结构排序.docx_第12页
第12页 / 共16页
数据结构排序.docx_第13页
第13页 / 共16页
数据结构排序.docx_第14页
第14页 / 共16页
数据结构排序.docx_第15页
第15页 / 共16页
数据结构排序.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

数据结构排序.docx

《数据结构排序.docx》由会员分享,可在线阅读,更多相关《数据结构排序.docx(16页珍藏版)》请在冰点文库上搜索。

数据结构排序.docx

数据结构排序

第8章排序

8.1排序的基本概念

8.2插入排序

8.3选择排序

8.4交换排序

本章主要知识点:

●排序的基本概念和衡量排序算法优劣的标准,其中衡量标准有算法的时间复杂度、空间复杂度和稳定性

●直接插入排序,希尔排序

●直接选择排序,堆排序

●冒泡排序,快速排序

8.1排序的基本概念

1.排序是对数据元素序列建立某种有序排列的过程。

2.排序的目的:

便于查找。

3.关键字是要排序的数据元素集合中的一个域,排序是以关键字为基准进行的。

关键字分主关键字和次关键字两种。

对要排序的数据元素集合来说,如果关键字满足数据元素值不同时该关键字的值也一定不同,这样的关键字称为主关键字。

不满足主关键字定义的关键字称为次关键字。

4.排序的种类:

分为内部排序和外部排序两大类。

若待排序记录都在内存中,称为内部排序;若待排序记录一部分在内存,一部分在外存,则称为外部排序。

注:

外部排序时,要将数据分批调入内存来排序,中间结果还要及时放入外

存,显然外部排序要复杂得多。

5.排序算法好坏的衡量标准:

(1)时间复杂度——它主要是分析记录关键字的比较次数和记录的移动次数。

(2)空间复杂度——算法中使用的内存辅助空间的多少。

(3)稳定性——若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。

8.2插入排序

插入排序的基本思想是:

每步将一个待排序的对象,按其关键字大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。

简言之,边插入边排序,保证子序列中随时都是排好序的。

常用的插入排序有:

直接插入排序和希尔排序两种。

8.2.1直接插入排序

1、其基本思想是:

顺序地把待排序的数据元素按其关键字值的大小插入到已排序数据元素子集合的适当位置。

例1:

关键字序列T=(13,6,3,31,9,27,5,11),

请写出直接插入排序的中间过程序列。

初始关键字序列:

【13】,6,3,31,9,27,5,11

第一次排序:

【6,13】,3,31,9,27,5,11

第二次排序:

【3,6,13】,31,9,27,5,11

第三次排序:

【3,6,13,31】,9,27,5,11

第四次排序:

【3,6,9,13,31】,27,5,11

第五次排序:

【3,6,9,13,27,31】,5,11

第六次排序:

【3,5,6,9,13,27,31】,11

第七次排序:

【3,5,6,9,11,13,27,31】

注:

方括号[]中为已排序记录的关键字,下划横线的关键字

表示它对应的记录后移一个位置。

2.直接插入排序算法

publicstaticvoidinsertSort(int[]a){

inti,j,temp;

intn=a.Length;

for(i=0;i

temp=a[i+1];

j=i;

while(j>-1&&temp

a[j+1]=a[j];

j--;

}

a[j+1]=temp;

}

}

初始关键字序列:

【13】,6,3,31,9,27,5,11

第一次排序:

【6,13】,3,31,9,27,5,11

第二次排序:

【3,6,13】,31,9,27,5,11

3、直接插入排序算法分析

(1)时间效率:

当数据有序时,执行效率最好,此时的时间复杂度为O(n);当数据基本反序时,执行效率最差,此时的时间复杂度为O(n2)。

所以当数据越接近有序,直接插入排序算法的性能越好。

(2)空间效率:

仅占用1个缓冲单元——O

(1)

(3)算法的稳定性:

稳定

8.2.2希尔(shell)排序(又称缩小增量排序)

1、基本思想:

把整个待排序的数据元素分成若干个小组,对同一小组内的数据元素用直接插入法排序;小组的个数逐次缩小,当完成了所有数据元素都在一个组内的排序后排序过程结束。

2、技巧:

小组的构成不是简单地“逐段分割”,而是将相隔某个增量d的记录组成一个小组,让增量d逐趟缩短(例如依次取5,3,1),直到d=1为止。

3、优点:

让关键字值小的元素能很快前移,且序列若基本有序时,再用直接插入排序处理,时间效率会高很多。

例2:

设待排序的序列中有12个记录,它们的关键字序列T=(65,34,25,87,12,38,56,46,14,77,92,23),请写出希尔排序的具体实现过程。

publicstaticvoidshellSort(int[]a,int[]d,intnumOfD){

inti,j,k,m,span;

inttemp;

intn=a.Length;

for(m=0;m

span=d[m];//取本次的增量值

for(k=0;k

for(i=k;i

temp=a[i+span];

j=i;

while(j>-1&&temp

a[j+span]=a[j];

j=j-span;

}

a[j+span]=temp;

}

}

}

}

算法分析:

开始时d的值较大,子序列中的对象较少,排序速度较快;随着排序进展,d值逐渐变小,子序列中对象个数逐渐变多,由于前面工作的基础,大多数记录已基本有序,所以排序速度仍然很快。

时间效率:

O(n(log2n)2)

空间效率:

O

(1)——因为仅占用1个缓冲单元

算法的稳定性:

不稳定

练习:

1.欲将序列(Q,H,C,Y,P,A,M,S,R,D,F,X)中的关键码按字母升序重排,则初始d为4的希尔排序一趟的结果是?

答:

原始序列:

Q,H,C,Y,P,A,M,S,R,D,F,X

shell一趟后:

P,A,C,S,Q,D,F,X,R,H,M,Y

2.以关键字序列(256,301,751,129,937,863,742,694,076,438)为例,写出执行希尔排序(取d=5,3,1)算法的各趟排序结束时,关键字序列的状态。

解:

原始序列:

256,301,751,129,937,863,742,694,076,438

希尔排序第一趟d=5256301694076438863742751129937

第二趟d=3076301129256438694742751863937

第三趟d=1076129256301438694742751863937

8.3选择排序

选择排序的基本思想是:

每次从待排序的数据元素集合中选取关键字最小(或最大)的数据元素放到数据元素集合的最前(或最后),数据元素集合不断缩小,当数据元素集合为空时选择排序结束。

常用的选择排序算法:

(1)直接选择排序

(2)堆排序

8.3.1直接选择排序

1、其基本思想

每经过一趟比较就找出一个最小值,与待排序列最前面的位置互换即可。

(即从待排序的数据元素集合中选取关键字最小的数据元素并将它与原始数据元素集合中的第一个数据元素交换位置;然后从不包括第一个位置的数据元素集合中选取关键字最小的数据元素并将它与原始数据集合中的第二个数据元素交换位置;如此重复,直到数据元素集合中只剩一个数据元素为止。

2、优缺点

优点:

实现简单

缺点:

每趟只能确定一个元素,表长为n时需要n-1趟

例3:

关键字序列T=(21,25,49,25*,16,08),请给出直接选择排序的具体实现过程。

原始序列:

21,25,49,25*,16,08

第1趟08,25,49,25*,16,21

第2趟08,16,49,25*,25,21

第3趟08,16,21,25*,25,49

第4趟08,16,21,25*,25,49

第5趟08,16,21,25*,25,49

publicstaticvoidselectSort(int[]a){

inti,j,small;

inttemp;

intn=a.Length;

for(i=0;i

small=i;//设第i个数据元素最小

for(j=i+1;j

if(a[j]

if(small!

=i){//当最小元素的下标不为i时交换位置

temp=a[i];

a[i]=a[small];

a[small]=temp;

}

}

}

3、算法分析

时间效率:

O(n2)——虽移动次数较少,但比较次数仍多。

空间效率:

O

(1)——没有附加单元(仅用到1个temp)

算法的稳定性:

不稳定

4、稳定的直接选择排序算法

例:

关键字序列T=(21,25,49,25*,16,08),请给出稳定的直接选择排序的具体实现过程。

原始序列:

21,25,49,25*,16,08

第1趟08,21,25,49,25*,16

第2趟08,16,21,25,49,25*

第3趟08,16,21,25,49,25*

第4趟08,16,21,25,49,25*

第5趟08,16,21,25,25*,49

publicstaticvoidselectSort2(int[]a){

inti,j,small;

inttemp;

intn=a.Length;

for(i=0;i

small=i;

for(j=i+1;j

if(a[j]

}

if(small!

=i){

temp=a[small];

for(j=small;j>i;j--)//把该区段尚未排序元素依次后移

a[j]=a[j-1];

a[i]=temp;//插入找出的最小元素

}

}

}

8.3.2堆排序

1.什么是堆?

2.怎样建堆?

3.怎样堆排序?

堆的定义:

设有n个数据元素的序列k0,k1,…,kn-1,当且仅当满足下述关系之一时,称之为堆。

解释:

如果让满足以上条件的元素序列(k0,k1,…,kn-1)顺次排成一棵完全二叉树,则此树的特点是:

树中所有结点的值均大于(或小于)其左右孩子,此树的根结点(即堆顶)必最大(或最小)。

例4:

有序列T1=(08,25,49,46,58,67)和序列T2=(91,85,76,66,58,67,55),判断它们是否“堆”?

2.怎样建堆?

步骤:

从第一个非终端结点开始往前逐步调整,让每个双亲大于(或小于)子女,直到根结点为止。

终端结点(即叶子)没有任何子女,无需单独调整

例:

关键字序列T=(21,25,49,25*,16,08),请建最大堆。

解:

为便于理解,先将原始序列画成完全二叉树的形式:

这样可以很清晰地从(n-1-1)/2开始调整。

publicstaticvoidcreateHeap(int[]a,intn,inth){

inti,j,flag;

inttemp;

i=h;

j=2*i+1;//j为i结点的左孩子结点的下标

temp=a[i];

flag=0;

while(j

=1){

//寻找左右孩子结点中的较大者,j为其下标

if(j

if(temp>=a[j])//a[i]>=a[j]

flag=1;//标记结束筛选条件

else{//否则把a[j]上移

a[i]=a[j];

i=j;

j=2*i+1;

}

}

a[i]=temp;

}

利用上述createHeap(a,n,h)函数,初始化创建最大堆的过程就是从第一个非叶子结点a[i]开始,到根结点a[0]为止,循环调用createHeap(a,n,h)的过程。

初始化创建最大堆算法如下:

publicstaticvoidinitCreateHeap(int[]a){

intn=a.Length;

for(inti=(n-1-1)/2;i>=0;i--)

createHeap(a,n,i);

}

3.怎样进行整个序列的堆排序?

*基于初始堆进行堆排序的算法步骤:

堆的第一个对象a[0]具有最大的关键码,将a[0]与a[n-1]对调,把具有最大关键码的对象交换到最后;

再对前面的n-1个对象,使用堆的调整算法,重新建立堆(调整根结点使之满足最大堆的定义)。

结果具有次最大关键码的对象又上浮到堆顶,即a[0]位置;

再对调a[0]和a[n-2],然后对前n-2个对象重新调整,…如此反复,最后得到全部排序好的对象序列。

例5:

对刚才建好的最大堆进行排序:

publicstaticvoidheapSort(int[]a){

inttemp;

intn=a.Length;

initCreateHeap(a);//初始化创建最大堆

for(inti=n-1;i>0;i--){//当前最大堆个数每次递减1

//把堆顶a[0]元素和当前最大堆的最后一个元素交换

temp=a[0];

a[0]=a[i];

a[i]=temp;

createHeap(a,i,0);//调整根结点满足最大堆

}

}

4、堆排序算法分析:

•时间效率:

O(nlog2n)。

•空间效率:

O

(1)。

•稳定性:

不稳定。

练习1:

以下序列是堆的是()

A.{75,65,30,15,25,45,20,10}B.{75,65,45,10,30,25,20,15}

C.{75,45,65,30,15,25,20,10}D.{75,45,65,10,25,30,20,15}

练习2:

有一组数据{15,9,7,8,20,1,7*,4},建成的最小堆为()。

A.{1,4,8,9,20,7,15,7*}B.{1,7,15,7*,4,8,20,9}

C.{1,4,7,8,20,15,7*,9}D.以上都不对

练习3:

已知序列{503,87,512,61,908,170,897,275,653,462},写出采用堆排序对该序列作非递减排列时的排序过程。

排序好的序列为:

61,87,170,275,462,503,512,653,897,908

8.4交换排序

交换排序的基本思想是:

利用交换数据元素的位置进行排序的方法。

交换排序的主要算法有:

1)冒泡排序

2)快速排序

8.4.1冒泡排序

1、基本思路:

每趟不断将记录两两比较,并按“前小后大”(或“前大后小”)规则交换。

2、优点:

每趟结束时,不仅能挤出一个最大值到最后面位置,还能同时部分理顺其他元素;一旦下趟没有交换发生,还可以提前结束排序。

例:

关键字序列T=(21,25,49,25*,16,08),请按从小到大的顺序,写出冒泡排序的具体实现过程。

初态:

21,25,49,25*,16,08

第1趟21,25,25*,16,08,49

第2趟21,25,16,08,25*,49

第3趟21,16,08,25,25*,49

第4趟16,08,21,25,25*,49

第5趟08,16,21,25,25*,49

3、冒泡排序算法

publicstaticvoidbubbleSort(int[]a){

inti,j,flag=1;

inttemp;

intn=a.Length;

for(i=1;i

flag=0;

for(j=0;j

if(a[j]>a[j+1]){

flag=1;

temp=a[j];

a[j]=a[j+1];

a[j+1]=temp;

}

}

}

}

4、冒泡排序的算法分析

时间效率:

O(n2)—因为要考虑最坏情况(数据元素全部逆序),当然最好情况是数据元素已全部排好序,此时循环n-1次,时间复杂度为O(n)

空间效率:

O

(1)—只在交换时用到一个缓冲单元

稳定性:

稳定—25和25*在排序前后的次序未改变

练习:

关键字序列T=(31,15,9,25,16,28),请按从小到大的顺序,写出冒泡排序的具体实现过程。

初态:

31,15,9,25,16,28

第1趟15,9,25,16,28,31

第2趟9,15,16,25,28,31

第3趟9,15,16,25,28,31

1、基本思想:

设数组a中存放了n个数据元素,low为数组的低端下标,high为数组的高端下标,从数组a中任取一个元素(通常取a[low])做为标准元素,以该标准元素调整数组a中其他各个元素的位置,使排在标准元素前面的元素均小于标准元素,排在标准元素后面的均大于或等于标准元素。

这样一次排序过程结束后,一方面将标准元素放在了未来排好序的数组中该标准元素应位于的位置上,另一方面将数组中的元素以标准元素为中心分成了两个子数组,位于标准元素左边子数组中的元素均小于标准元素,位于标准元素右边子数组中的元素均大于等于或标准元素。

对这两个子数组中的元素分别再进行方法类同的递归快速排序。

算法的递归出口条件是low≥high。

例、关键字序列T=(60,55,48,37,10,90,84,36),请按从小到大的顺序,写出快速排序的具体实现过程。

快速排序算法各次快速排序过程

3、快速排序算法

publicstaticvoidquickSort(int[]a,intlow,inthigh){

inti,j;

inttemp;

i=low;

j=high;

temp=a[low];//取第一个元素为标准数据元素

while(i

//在数组的右端扫描

while(i

if(i

a[i]=a[j];

i++;

}

//在数组的左端扫描

while(i

if(i

a[j]=a[i];

j--;

}

}

a[i]=temp;

if(low

if(i

}

4、快速排序算法分析:

时间效率:

一般情况下时间复杂度为O(nlog2n),最坏情况是数据元素已全部正序或反序有序,此时每次标准元素都把当前数组分成一个大小比当前数组小1的子数组,此时时间复杂度为O(n2)

空间效率:

O(log2n)—因为递归要用栈

稳定性:

不稳定—因为有跳跃式交换。

练习:

已知序列{503,87,512,61,908,170,897,275,653,462},给出采用快速排序对该序列作非递减排序时每趟的结果。

第一趟:

【4628727561170】503【897908653512】

第二趟:

【1708727561】462503【512653】897【908】

第三趟:

【6187】170【275】462503512【653】897908

第四趟:

61【87】170275462503512653897908

最后排序结果:

6187170275462503512653897908

1.插入排序是稳定的,选择排序是不稳定的。

2.堆排序所需要附加空间数与待排序的记录个数无关。

3.对有n个记录的集合进行快速排序,所需时间确定于初始记录的排列情况,在初始记录无序的情况下最好。

4.直接插入排序在最好情况下的时间复杂度为(A)

A.O(n)B.O(nlog2n)C.O(log2n)D.O(n2)

5.数据序列{8,9,10,4,5,6,20,1,2}只能是(C)算法的两趟排序后的结果。

A.直接选择排序B.冒泡排序C.直接插入排序D.堆排序

6.用直接插入排序对下面4个序列进行递增排序,元素比较次数最少的是(C)

A.94,32,40,90,80,46,21,69B.32,40,21,46,69,94,90,80

C.21,32,46,40,80,69,90,94D.90,69,80,46,21,32,94,40

7..以下排序算法中,(B)不能保证每趟排序至少能将一个元素放到其最终位置上。

A.快速排序B.希尔排序C.堆排序D.冒泡排序

8.对关键字{28,16,32,12,60,2,5,72}序列进行快速排序,第一趟从小到大一次划分结果为(B)

A.(2,5,12,16)26(60,32,72)B.(5,16,2,12)28(60,32,72)

C.(2,16,12,5)28(60,32,72)D.(5,16,2,12)28(32,60,72)

9.若用冒泡排序对关键字序列{18,16,14,12,10,8}进行从小到大的排序,所需进行的关键字比较总次数是(B)。

A.10B.15C.21D.34

10.一组记录的关键字为{45,80,55,40,42,85},则利用堆排序的方法建立的初始堆为(B)。

A.{85,80,45,40,42,55}B.{85,80,55,40,42,45}C.{85,80,55,45,42,40}D.{85,55,80,42,45,40}

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

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2