(自用,侵删)
使一组记录成为按关键字有序的序列
排序的分类原则
存储介质 内部排序、外部排序
比较器 串行排序、并行排序
主要操作 比较、基数
辅助空间 原地、非原地
稳定性 稳定、非稳定
自然性 自然、非自然
按照分类原则不同将内部排序分为5类:插入、交换、选择、归并、分配
几种排序方法,掌握比较次数、移动次数、辅助空间(时间复杂度和空间复杂度)、稳定性
一、插入排序
将记录一趟趟地插入已排好的序列中
按查找方法不同的以下几种方法
1.直接插入排序
最简单的排序方法,逐趟插入,有序表记录增1
初始关键字 5 3 665 121 45
i=2 (3 5) 665 121 45
i=3 (3 5 665) 121 45
...
插入方法:
从前向后顺序比较
从后向前,r[0]处加入监视哨防止出界
时空复杂度分析
n-1趟
最好 最坏 平均
比较次数: n-1
移动次数: 0
时间复杂度:O() 空间复杂度:O(1) (辅助空间r[0])
特点:适合记录基本有序的情况
2.折半插入排序
查找操作为折半查找
时空复杂度分析
比较次数:插入第i个记录时为:
移动次数:与直接插入相同,依赖初始序列
时间复杂度:O() (减少比较次数,移动次数不变)
空间复杂度:O(1) (辅助空间r[0])
特点:只能用于顺序结构,不能用链式(难定位要一个个数)
适合无序,n较大情况
3.希尔排序(缩小增量排序)
每趟取增量排序:递减、互质、最后一个增量值为1
从"减少记录个数"、"序列基本有序"两方面对直接插入排序进行改进
增量选取:3、2、1
初始关键字: 88 2 33 20 43 909 772
88 20 772
2 43
33 909
一趟排序结果:20 2 33 88 43 909 772
20 33 43 772
2 88 909
二趟排序结果:20 2 33 88 43 909 772
三趟排序结果:2 20 33 43 88 772 909
时间复杂度: (此为经验公式,具体和增量序列的选取有关)
空间复杂度:O(1)
特点:不稳定
只能用于顺序结构
适合初始记录无序,n较大的情况
二、交换排序
两两比较,不满足序列要求进行交换
1.冒泡排序
一种最简单的交换排序方法,逐趟比较,关键字小(大)的记录左(右)移
2 2 2
5 5 5
43 6 6
6 23 23
23 43 43
45 45 45
342 65 65
65 342
初始关键字 第一趟排序后 第二趟排序后
最后一趟没有进行交换记录的操作,完成排序
时空复杂度分析
最好情况 最坏情况 平均情况
关键字比较次数KCN n-1
记录移动次数RMN 0
时间复杂度: 空间复杂度:
特点:稳定
可用于链式存储结构
移动记录次数多,平均时间性能比直接插入算法差,不适用于初始记录无序n较大的情况
2.快速排序
冒泡算法改进,任取一关键字作为枢轴,设其关键字为pivotkey
- 将pivotkey暂存r[0](这里为第一个记录)
- 从最右位置开始左移
- 遇到比pivotkey小的,放到pivotkey位置
- 从左边移动后的位置开始右移
......(这里使用了两个指针)
初始关键字 8 78 45 32 9 6 35
进行一次交换 6 78 45 32 9 35
进行两次交换 6 45 32 9 78 35
进行三次交换 6 8 45 32 9 78 35
第一趟排序
初始状态 {8 78 45 32 9 6 35}
一趟排序结果 {6} 8 {45 32 9 78 35}
二趟排序结果 6 8 { } 45 {78}
...
快速排序全过程
时空复杂度分析
最好情况:类似折半查找,根据递归算法,总排序时间
最坏情况:n-1趟,第i趟进行n-i次比较
(退化到简单排序水平)
平均情况:(取第一个最后一个和中间的记录,取中值作为枢轴记录,避免最坏情况)
特点:不稳定
适用于顺序结构(需要确定上下界)
适合无序,n较大情况
三、选择排序
每趟从未排序记录中选关键字最小记录放在已排序记录的最后
1.简单选择排序
也叫直接选择排序
初始关键字 5 9 56 27 78 5*
一趟排序结果 (5) 9 56 27 78 5*
二趟排序结果 (5 5*) 56 27 78 9
三趟排序结果 (5 5* 9) 27 78 56
...
算法分析
最好情况(正序) 最坏情况(逆序)
比较次数
移动次数 0 3(n-1)
时间复杂度: 空间复杂度:
特点:稳定(采用“交换记录”策略,可以产生不稳定现象)
可用于链式存储结构
移动记录次数少,记录占用空间较多时,比直接插入排序快
2.堆排序
一种树形选择排序
大根堆:且
小根堆:且
通过堆的性质取记录,进行堆排序需要解决建初堆和调整堆的问题
调整堆:改变栈顶元素后使其变成一个新的堆
- 取根节点,将最后一个元素放到根节点
- 将堆顶元素与左右子树根结点进行大小比较并交换调整(如大根堆取左右较大的数),直至叶子结点
- 反复进行
67 3 34 9
34 28 34 28 12 28 12 28
12 6 7 9 12 6 7 9 3 6 7 9 3 6 7 34 ...
3 97 97 97
大根堆 3和97交换 调整后的新堆 9和34交换
建初堆:将一个无序序列建成一个堆
从最后一个非叶子结点开始依次调整n/2、n/2-1、...、1
一组序列 43 54 9 23 4 12 3 利用筛选法调整为小根堆
43 43 43 3
54 9 54 3 4 3 4 9
23 4 12 3 23 4 12 9 23 54 12 9 23 54 12 43
初始序列 筛选3 筛选53 筛选43
时间复杂度: 空间复杂度:
特点:不稳定
只能用于顺序结构
记录较高时高效,不宜用于记录较少时
四、归并排序
将两个(2-路归并)或两个以上有序表合并成一个有序表
2-路归并
初始关键字 [2] [23] [121] [34] [3] [32]
一趟归并 [2 23] [34 121] [3 32]
二趟归并 [2 23 34 121] [3 32]
三趟归并 [2 3 ]
时间复杂度: (趟,每趟比较次数不超过n,移动次数为n)
空间复杂度:
特点:稳定
可用于链式结构,不需要附加存储空间,递归实现需开辟相应递归工作栈
五、基数排序
分配(类似于桶)
初始状态 231 213 344 322 564 232
0 1 2 3 4
第一趟分配 231 322 213 344
232 564
第一趟收集 231 322 232 213 344 564
第二趟分配 0 1 2 3 4 5 6
213 322 231 344 564
232
第二趟收集 213 322 231 232 344 564
第三趟分配 0 1 2 3 4 5
213 322
231 344 564
232
第三趟收集 213 231 232 322 344 564
时间复杂度:O(d(n+rd)) (关键字为d,取值范围为rd)
每个记录有d个关键字(上例d=3),每一趟f分配时间复杂度为O(n),收集时间复杂度为O(rd)
空间复杂度:O(n+rd)
辅助空间为2n个队列指针,(链式增加n个指针域空间)
特点:稳定
可用于链式和顺序
时间复杂度突破比较下界,达到O(n)
需要知道关键字主次关系和取值范围