1022 字
5 分钟
排序
2024-09-17
无标签
概念
- 稳定性
- 内部排序 外部排序
- 待排序的容器的物理排列方式 顺序 链式
- 时空复杂度
- 基于比较的排序的时间复杂度下限 一个不精确的下界
内部排序
基于插入
- 直接插入
- 折半插入
- 希尔排序
基于交换
- 冒泡
- 快排
findpivot(arr, low, high) {
pivot := arr[low]
i := low
j := high
while i < j {
while i < j and arr[j] >= pivot { j-- }
arr[i] = arr[j]
while i < j and arr[i] <= pivot { i++ }
arr[j] = arr[i]
}
arr[i] = pivot
return i
}
quicksort(arr, low = 0, high = arr.len - 1) {
if(high <= low) return
pivot := findpivot(arr,low,high)
quicksort(arr,low,pivot-1)
quicksort(arr,pivot+1,high)
}
基于选择
- 选择排序
- 堆排序 堆
其他
- 归并
- 基数
- MSD高位优先,先根据高位关键字排序,分为若干个子序列,子序列内再用次关键字排序
- LSD优先,先对列表按次关键字排序,再按主关键字排序
- 计数
比较
| 空间复杂度 | 时间复杂度 | 最坏时间复杂度 | 最好时间复杂度 | 稳定性 | 特点 | 适用容器 | |
|---|---|---|---|---|---|---|---|
| 直接插入 | ,完全逆序 | ,有序 | O | 在基本有序的情况下表现还行,第n趟后前n+1个元素有序 | 数组,链表 | ||
| 折半插入 | ,完全逆序 | ,有序 | O | 在基本有序的情况下表现还行,第n趟后前n+1个元素有序。 对于规模一定的数组,比较总次数一定 | 数组 | ||
| 希尔排序 | X | 数组 | |||||
| 冒泡排序 | O | 当某一趟没有发生交换时即可完成排序 前n趟确定n个最小值放在前n个位置作为最终位置 | 数组链表 | ||||
| 快速排序 | 跟递归深度有关平均最坏 | 逆序或者顺序的情况 | X | 每一趟确定pivot的最终位置 | 数组 | ||
| 选择排序 | X | 对于规模一定的数组,比较总次数一定 前n趟确定n个最小值放在前n个位置作为最终位置 | 数组链表 | ||||
| 堆排序 | X | 前n趟确定n个最大值放在后n个位置作为最终位置 | 数组 | ||||
| 归并 | O | 归并段内有序第i趟后有个有序归并段 | 数组 | ||||
| 基数 | 要开辟r个队列 | 如果关键字由d个子关键字组成,那么一共要进行d趟的分配搜集操作,分配的复杂度是,搜集的复杂度是,故总的复杂度是 | O | 不采用比较来进行排序故运行开销与初始状态无关 仅适用于整形排序,整形范围不宜过大 | 链表 | ||
| 计数 | - |
外部排序
- 排序 = IO + 内部排序生成初始归并段 + IO + 多趟内部归并 + IO
- 输入次数 = 输入次数 = (归并趟数量 + 1)X总磁盘块数
- IO次数 = 2X(归并趟数量 + 1)X总磁盘块数
- 故归并树的深度越小IO次数越少即k路归并的k值越大IO次数越小
- 或者减少初始归并段段数量
- 内部归并采用败者树可以做到比较次数与k值无关
- https://oi-wiki.org/ds/loser-tree/
- 败者树的维护一定是从叶子到根的区别与堆
- 使用置换选择排序生成初始归并段,使得生成的初始归并段尽可能少 最小的归并段长度是WA的长度,最大的归并段长度即FI的长度

- 最佳归并树 使用置换选择排序生成的是长度不一的初始归并段,使用最佳归并树来组织归并顺序使得IO次数最少。最佳归并树是一颗K叉哈夫曼树,归并过程中的IO次数是其WPL的两倍
- 若初始归并段的数量无法恰好满足,补充长度为0的“虚段” 设采用K路归并,初始归并段数量为n,若 ,则不用补充虚段,否则,补充个虚段
