交换类排序-快速排序
可以理解为划分交换排序几乎最快的排序方法。(分治的策略)
分治法的基本思想
将原有问题分解为若干个规模更小但结构与原问题相似的自问题,递归地解决这些子问题,然后
将这些子问题的解组合为原问题的解
算法步骤
- 从一个待排序列中任意选择一个记录
- 以该记录的关键字作为“枢纽”
- 凡是关键字小于枢纽的记录均移动至该记录之前;反之,移动至该记录之后
- 一趟排序后,分割成左右两个子序列,再对两个子序列中进行快排
代码示例
1 | int QKpass(RecordList L,int low,int high){ |
输出结果:无
性能分析
- 快排的时间代价一般取决于枢纽的选择
- 最简单的办法是选取第一个或最后一个元素作为枢纽,但也是最差的情况,因为总是一个序列是为空,时间复杂度为O(n^2)
- 可以选取中间位置(low+high)/2作为记录关键字的枢纽值,可以有效平分,最好的情况每次都分为长度相同的子序列,其时间复杂度为O(nlog以二为底的n次方)
- 快速排序每次移动记录跨度比较大,所以快排是不稳定的
时间复杂度 | 最好情况 | 最坏情况 | 平均复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
快速排序 | O(nlog2n) | O(n^2) | O(nlog2n) | O(nlog2n) | 不稳定 |
选择类排序-堆排序
为了弥补树形选择排序占用较多辅助空间的问题,利用堆的特性进行排序的方法
堆的定义
堆是满足下列性质的数列:
将数列看成一颗完全二叉树,则堆或是空树或是满足下列特性的完全二叉树:
其左、右子树分别是堆,并且当左右子树不空时,根节点的值小于(或大于)左右子树根节点的值。
算法步骤
- 首先将待排序的无序序列建初始小顶堆:堆顶元素为最小值
- 然后将堆顶记录和堆尾记录交换,并将最后一个记录的枝剪掉
- 调整剩余的记录序列,利用筛选法重新调整为一个新堆,堆顶元素为次最小值,然后交换并剪枝
- 进行n-1次操作后,直到所有元素输出的元素为一个有序序列
代码示例
1 | //堆的筛选 |
输出结果:无
性能分析
- 堆排序主要花费在建初始堆和调整建新堆反复的筛选上
- 对于深度为k的堆,筛选中关键字的比较次数最多为2(k-1)次。堆排序的时间复杂度为O(nlog2n)
- 只需要一个辅助空间,故空间复杂度为O(1)
- 堆排序仍然是大跨度调整了元素位置,为不稳定的排序
时间复杂度 | 最好情况 | 最坏情况 | 平均复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
堆排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) | 不稳定 |