数据结构 排序-详细介绍

排序

1.排序(sort)的概念

所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。

2.排序的稳定性
在待排序的文件中,若存在多个关键字相同的记录**,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的**;若具有相同关键字的记录之间的相对次序发生变化,则称这种排序方法是不稳定的。

注意:
排序算法的稳定行是针对所有输入实例而言。即在所有可能的输入实例中,只要有一个实例使得算法不满足稳定性要求,则该算法就是不稳定的。

3.排序方法的分类

(1)按是否涉及数据的内/外存交换分
在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内/外存交换,则称之为排序(简称内排序);反之,若排序过程中要进行数据内/外存交换,则称之为外部排序。

注意:
a.内排序适用于记录个数不很多的小文件
b.外排序适用于记录个数太多,不能一次将其全部记录放入内存的大文件

(2)按策略划分内部排序方法

内部排序可以分为五类:插入排序/选择排序/交换排序/归并排序和分配排序。

4.排序算法性能评价
(1)评价排序算法好坏的标准

a.执行算法需要的时间
b.算法所需要的辅助空间
c.算法本身的复杂程度

(2)排序算法的时间开销
一般情况下,用算法执行中关键字之间的比较次数和记录的移动次数来衡量。

(3)排序算法的空间复杂度
若排序算法所需要的辅助空间并不依赖于问题的规模n,空间复杂度O(1),则成这样的排序为就地排序。非就地排序的空间复杂度一般为O(n)。

5.待排序记录的数据类型定义
在这里插入图片描述

在这里插入图片描述

第二节 插入排序

插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序列的子文件中的适当位置,直到全部记录插入完成为止。插入排序主要包括:直接插入排序和希尔排序。

一.直接插入排序

1.排序思想

假设待排序的记录存放在数组R[1…n]中,初始时,R[1]自成一个有序区,无序区R[2…n].从i=n为止,依次将R[i]插入当前的有序区R[1…i-1]中,生成含n个记录的有序区。

2.实例分析
【例】给定一组关键字(46,39,17,23,28,55,18,46).要求按直接插入排序算法给出每一趟排序结果。

在这里插入图片描述

3.算法描述
在这里插入图片描述
4.算法分析

(1)哨兵的作用
算法中引进的附加记录R[0]称为哨兵(Sentinel),哨兵有两个作用:

a.进入查找(插入位置)循环之前,它保存了R[i]的副本,不至于因记录后移而丢失R[i]的内容;
b.它的主要作用是:在查找循环中“监视”下标变量J是否越界。一旦越界(即j=0),因为R[0].key和自己比较,循环判定条件不成立使得查找循环结束,从而避免了在该循环内的每一次均要检测j是否越界(即省略了循环判定条件“j>=1”),使得测试查找循环条件的时间大约减少了一半。

(2)算法的时间性能分析

对于具有n个记录的文件,要进行n-1趟排序。

各种状态下的时间复杂度:

在这里插入图片描述
(3)算法的空间复杂度分析

算法所需要的的辅助空间是一个监视哨,辅助空间复杂度S(n)=O(1). 是一个就地排序。

(4)直接插入排序是稳定排序的方法

二、希尔排序

1、排序思想

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离高为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2 <d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-1<…d2<d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上时一种分组插入方法。

2.实例分析

初始关键字序列为(36,25,48,27,65,25,43,58,76,32)。其增量序列的取值依次为5,3,1,排序过程如图所示。
在这里插入图片描述
在这里插入图片描述
4.算法分析

(1)增量序列的选择
a.最后一个增量必须为1.
b.应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。

(2)Shell 排序的时间性能优于直接插入排序,实验表明,当n较大时,比较和移动的次数约
在 n^ 1.25 , 到1.6n^1.25 之间。

(3)算法空间复杂度分析
算法空间复杂度为O(1).是一个就地排序。

(4)稳定性
希尔排序是不稳定的。

第三节 交换排序

交换排序的基本思想是:两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。 应用交换排序基本思想的主要排序方法有:冒泡排序和快速排序。

一、冒泡排序

1.排序思想

通过相邻元素之间的比较和交换,使关键字较小的元素逐渐从底部移向顶部,关键字较大的元素逐渐下移(后移),小的上浮,大的下沉,所以冒泡排序又被称为“起泡”排序。

第一趟扫描:依次比较(R[n],R[n-1]…R[2],R[1]);对于每对气泡(R[j+1],R[j]),若R[j+1].key<R[j].key ,
则交换R[j+1]和R[j]的内容。第一趟扫描完毕时,“最轻”的起泡酒漂浮到该区间的顶部,即关键字最小的记录被放在最高位置R[1]上。然后再对R[n]-R[2]的记录进行第二趟排序,使次小关键字的元素被上浮到R[2]中,重复进行,n-1趟后,整个冒泡排序结束。

在这里插入图片描述
在这里插入图片描述
4.算法分析

(1)算法的最好时间复杂度
若待排序记录为有序(最好情况),则一趟扫描完成,关键比较次数为n-1次且没有移动,比较的时间复杂度为O(n)。

(2)算法的最坏时间复杂度

若初始文件时反序的,需要进行n-1趟排序。每趟排序要进行n-i次关键字的比较(1<= i <=n-1),且每次比较都必须移动记录三次来达到交换记录位置。总的比较次数为:(n-1)+(n-2)+…+1=(n-1)n/2; 总的移动次数为3n(n-1)/2 . 在平均情况下,比较和移动的总次数大约为最坏情况下的一半,所以,冒泡排序算法的时间复杂度为O(n^2).

(3)算法的空间复杂度
冒泡排序的空间复杂度为O(1),是就地排序

(4)算法稳定性
冒泡排序是稳定的。

【例】设计一个修改冒泡排序算法以实现双向冒泡排序的算法。

双向冒泡排序则是交替改变扫描方向,即一趟从下向上通过两个相邻关键字的比较,将关键字最小的记录换至最上面位置,再一趟则是从第二个记录开始向下通过两个相邻记录关键字的比较,将关键字最大的记录换至最下面的位置;然后再从倒数第二个记录开始向上两两比较至顺数第二个记录,将其中关键字较小的记录换至第二个记录位置,再从第三个记录向下至倒数第二个记录两两比较,将其中较大关键字的记录换至倒数第二个位置,依次类推,直到全部有序为止。

在这里插入图片描述
??当排序本身R[j].key >R[j+1].key 是否 NoSwap=1 循环终止。

二,快速排序

1.排序思想

快速排序的基本思想是: 首页在当前无序区R[low…high] 中任取一个记录作为排序比较的基准(不妨设为x),用此基准将当前无序区划分为两个较小的无序区R[low…i-1]和R[i+1…high] ,并使左边的无序区中所有记录的关键字均小于等于基准的关键字,右边的无序区中所有记录的关键字均大于等于基准的关键字,而基准记录x则位于最终排序的位置i上, 这个过程称为一趟快速排序(或一次划分)。当R[low…i-1]和R[i+1…high]均非空时,分别对他们进行上述划分,直到所有的无序区中的记录均已排好序为止。

一趟快速排序的具体操作是:设两个指针i和j,它们的初值分别为low和high,基准记录x=R[i],首先从j所指位置起向前搜索找到第一个关键字小于基准x.key的记录存入当前i所指向的位置上,i自增1,然后再从i所指位置起向后搜索,找到第一个关键字大于x.key的记录存入当前j所指向的位置上, j自减1;重复这两步,直至i等于j为止。

在这里插入图片描述
4.算法描述

在这里插入图片描述
4.算法分析

(1)算法时间复杂度
快速排序的时间复杂度为O(nlog2n). 快速排序方法被认为是排序时间效率非常高的一种方法,但是,当参加排序的原始序列已经是一个按值有序或基本有序的序列时,快速排序方法的时间效率降到最低,这种情况下其时间复杂度为O(n^2)

(2)算法空间复杂度
快速排序的空间复杂度为0(log2n).

(3)算法稳定性
快速排序方法是一种不稳定的排序方法。

第四节 选择排序

选择排序(Selection Sort)的基本思想是:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已经拍好序的子文件的最后,直到全部记录排序完毕。常用的选择排序方法有直接选择排序和堆排序。

一,直接选择排序

1.排序思想

直接选择排序(Straight Select Soft)是一种简单的排序方法。它的基本思想是:每次葱饼待排序的无序区中选择出关键字值最小的记录,将该记录与该区中的第一个记录交换位置。初始时,R[1…n]为无序区,有序区为空。 第一趟排序是在无序区R[1…n]中选出最小的记录,将它与R[1]交换,R[1]为有序区;第二趟排序是在无序区R[2…n]中选出最小的记录与R[2]交换,此时R[1…2]为有序区;依次类推,做n-1趟排序后,区间R[1…n]中记录递增有序。

2.实例分析

在这里插入图片描述
第七趟排序之后得到:11 , 24 , 33 , 38 , 38 , 65 , 76 , [82]

4.算法分析

(1)时间复杂度
无论文件初始状态如何,在第i趟排序中选出最小关键字的记录需要n-1次比较,总比较次数为(n-1)+(n-2)+…+1 = n(n-1)/2;
当初始文件为正序时,移动次数为0;文件初态为反序时,每趟排序均要执行交换操作,每次交换需要移动3次,总的移动次数取最大值3(n-1)。
直接选择排序的平均时间复杂度为O(n^2).

(2)空间复杂度
直接选择排序的空间复杂度是O(1),是一个就地排序。

(3)稳定性
直接选择排序是不稳定的。

【例】假设采用不带头结点的单链表作为存储结构,试编写一个直接选择排序(升序)的算法。

设单链表结点类型和链表类型的定义如下:
在这里插入图片描述

在这里插入图片描述
(2)按直接选择排序算法思想,每次选择到最小的结点后,将其脱链并加入到一个新链表中,这样可避免结点域值交换,最后将新链表的头指针返回。

在这里插入图片描述
在这里插入图片描述
二,堆排序

1.堆排序定义

n个关键字序列K1,K2…Kn称为堆,当且仅当该序列满足如下关系:
(1)Ki<=K2i 且 Ki<=K2i+1 或(2)ki>=k2i+1(i<=i<=[n/2])

前者称为小根堆,后者称为大根堆。

在这里插入图片描述

2.堆排序的思想

从小到大排序的步骤:
第一步:将参加排序的原始序列转换为第一大根堆(建初始堆)。
第二步:把堆的第一个元素(最大值元素)与堆的最后那个元素交换位置。
第三步:将在第二步中“去掉”最大值元素后剩下的元素组成的序列重新调整为一个新的堆。
第四步:重复第二步与第三步n-1次,直到排序结束。

3.实例分析
在这里插入图片描述

第五节 归并排序

1,二路归并排序的思想

初始时将待排序列R[1…n]看成n个长度为1的有序序列,通过第一趟两两归并后,得到[n/2]个长度为2的有序序列,然后再两两归并,得到[n/4]个长度为4的有序序列,如此重复,直到得到一个长度为n的有序序列。

2.实例分析

在这里插入图片描述
3,算法分析
二路归并排序法需要进行log2n 向上取整趟,其时间复杂度为0(nlog2n),空间复杂度0(n).是一种稳定的排序方法。

第六节 分配排序

分配排序的基本思想:排序过程无需比较关键字,而是通过“分配”和“收集”过程来实现排序。常用的分配排序有 箱排序和基数排序。

一,箱排序

1,箱排序的基本思想

箱排序也称桶排序,其基本思想是:设置若干个箱子,依次扫描待排序的记录R[0],R[1]…,R[n-1],把关键字等于k的记录全部都装入到k个箱子里(分配),然后按序号依次将各非空的箱子首尾连接起来(收集)。

【例】要将依法混洗的52张扑克牌按点数A<2<…<J<Q<K排序,需要设置13个箱子,排序时依次将每张牌按点数放入相应的箱子里,然后依次将这些箱子首尾相接,就得到了按点数递增排序的一副牌。

2,算法简析

箱排序的时间复杂度为O(n).箱排序是稳定排序,箱排序只适用于关键字取值范围较小的情况,否则所需要的箱子的数目太多,会导致存储空间的浪费和计算时间的增长。

二.基数排序

基数排序(Radix Sort)是对箱排序的改进和推广。

1.基数排序的思想

基数排序的基本思想是:从低位到高位依次对K^j (j=d-1,d-2…0)进行箱排序,在d趟箱排序中,所需的箱子树就是基数rd,这就是“基数排序”名称的由来。

2.实例分析

在这里插入图片描述
3.算法分析

基数排序的时间复杂度是O(d*(rd+n)).其中rd是基数,d是关键字的位数,n是元素个数,基数排序所需的辅助存储空间为O(n+rd).基数排序是稳定的。

第七节 内部排序方法的分析比较

1.时间复杂度

a.直接插入,直接选择,冒泡排序算法的时间复杂度为O(n^2).
b.快速,归并,堆排序算法的时间复杂度为O(nlog2n).
c.希尔排序算法的时间复杂度很难计算,有几种较接近的答案:O(nlog2n)或O(n^1.25).
d.基数排序算法的时间复杂度为O(d*(rd+n)),其中rd是基数,d是关键字的位数,n是元素个数。

2.稳定性

a.直接插入,冒泡,归并和基数排序算法是稳定的;
b.直接选择,希尔,快速和堆排序算法是不稳定的。

3.辅助空间(空间复杂度)

a.直接插入,直接选择,冒泡,希尔和堆排序算法需要辅助空间为O(1)。
b.快速排序算法需要辅助空间为O(log2n).
c.归并排序算法需要辅助空间为O(n).
d.基数排序算法需要辅助空间为O(n+rd).

4.选取排序方法时需要考虑的主要因素

a.待排序的记录个数
b.记录本身的大小和存储结构
c.关键字的分布情况
d.对排序稳定性要求
e.时间和空间复杂度等

5.排序方法的选取

a.若待排序的一组记录数目小于(如n<=50)时可以采用插入排序或选择排序。
b.若n较大时,则应采用快速排序、堆排序或归并排序
c.若待排序记录按关键字基本有序时,则事宜选择直接插入排序或冒泡排序。
d.当n很大,而且关键字位数较少时,采用链式基数排序较好。
e.关键字比较次数与记录的初始排序顺序无关的排序方法是选择排序

6.排序方法对记录存储方式的要求

一般的排序方法都可以在顺序结构(一维数组)上实现。当记录本身信息量较大时,为了避免移动记录耗费大量的时间,可以采用链式存储结构。例如插入排序,归并排序,基数排序易于在链表上实现,使之减少记录的移动次数,但有的排序方法,如快速排序、堆排序在莲表示却难于实现,在这种情况下,可以提取关键字建立索引表,然后对索引表进行排序。

在这里插入图片描述

小结:

着重讨论有关内部排序的一些常用方法,主要有插入排序、交换排序、选择排序、归并排序及基数排序,介绍其排序思想、排序过程、算法实现时间和空间性能的分析及各种排序方法的比较和选择。

在掌握所介绍的几种主要排序算法的基本思想,同时还应该学会基本的算法分析基数,比较这些算法的时间和空间复杂性,从而能够在实际应用中正确选择适当的排序方法。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值