去年我在网易公开课参加了浙大公开课-<数据结构>的学习.讲师是陈越姥姥和何钦铭先生.
今天我再次将之前的笔记做了整理.希望方便盆友们的学习.
排序算法是否稳定?
两个相同数据的先后顺序能否保证在排序后不变.
内排序和外排序
我们知道,按照待排序数据能否在你的内存中放得下,分为内排序和外排序.
1冒泡排序的效率:
最快0(n)
最坏O(n^2)
优点:
- 简单
- 适合链表操作(只比较和修改相邻的数据)
- 稳定.
2插入排序的效率:
最快0(n)
最坏O(n^2)
优点:
- 简单
- 操作较少.每次比较最多移动一个数据.(相较于冒泡排序)
- 序列基本有序,则插入排序简单高效.
- 稳定.
逆序对:
对于下标i>j,如果A[i]>A[j],则称(i,j)是一对逆序对(inversion).
插入排序:T(N,I)=O(N+I);(I为逆序对)
N(N-1)/4个逆序对.
交换比较相邻的数据,每次对多消去一个逆序对.所以……
3希尔排序Sheel
插入的简便+克服插入每次只能消除一个逆序对.
定义增量序列:
原始序列是:n/2,n/4,……1;
但是这样的序列增量元素不互质,小增量就可能根本不起作用.
两种增量序列:
Hibbard增量序列:
Dk=2^k-1 (相邻互质)
Sedgewick增量序列:
9*4^i-9*2i+1
或者
4^i-3*2^i+1
这两种增量序列Sedgewick最坏情况和平均时间复杂度都要好一些.
4堆排序
回顾选择排序:
找到最小元,将该元放到队尾.重复这个过程.
O(n)
T(n^2)
选择排序,
改进选择排序的时间效率集中在了:快速找到最小元.
使用最小堆:
堆排序是对选择排序寻找最小元的改进.
时间复杂度:时间复杂度(nlogn)
但是最小堆排序后果是:需要一倍的内存.
进一步的改进是使用最大堆.
对于随机排列的N个不同元素
时间复杂度O(2NlogN-O(Nlog logN))
但是实际效果不如用Sedgewick增量序列的希尔排序.
其伪代码如下:
什么时候适合选择排序(堆排序)?
排序操作不需要完全执行时,选择排序较为适合。
举个栗子:要得到最大的前K个的数。
3 归并排序-外排序时非常有用
核心:有序子咧的归并
T(N)=O(N)
递归算法:
分而治之
T(N)=T(N/2)+T(N/2)+O(N) => T(N)=O(NlogN)
稳定
非递归算法:
NLogN
稳定
4 快速排序
分而治之
N<2退出
1分:随机挑选主元.划分两个子集.
2治:两边递归
主元挑选方法
划分两个子集的方法
最好情况:
主元每次最好中分.
T(N)=O(NlogN)
主元的挑选方法:
头中尾取中位数.或者多个位置取中位数.
对于小规模数据(例如N<100)可能还不如插入排序快.
所以一种策略是:
当递归的数据规模充分小时,停止递归,直接调用简单排序.
这个阀值(Cutoff).
快速排序代码实现: