排序(升序)
0. 冒泡排序
0.1 算法思想
- 临近的数字两两进行比较,逆序则交换,一趟过去最大的元素被放到最后一位。
- 再对前n-1个元素进行上述操作,直到第一个元素
0.2 性能分析
- 最坏情况:
- 比较次数:(N-1)+(N-2)+……+2+1=N(N-1)/2~ N2/2
- 交换次数:同上
- 最好情况:
- 比较次数:(N-1)+(N-2)+……+2+1=N(N-1)/2~ N2/2
- 交换次数:0
0.3 特点
存在不足:就是本来位于前面的较小数被交换到后面
1. 选择排序
1.1 基本思想
- 找到数组中最小的元素
- 将它与数组的第一个元素交换位置
- 再次,剩下的元素找最小的元素与数组的第二个元素交换位置
- 直到最后一个元素
即不断选择剩余元素的最小者,与第n个元素交换,直至整个数组有序
1.2 性能分析
- 交换次数总是N
- 比较次数约为
N2/2
- 0-N-1的任意i都会进行 N−1−i 次比较,故 (N-1)+(n-2)+……2+1=N(N-1)/2~ N2/2 次比较
1.3 特点
- 当前索引左边都是有序的
- 一次确定一个元素的位置
- 数据移动最少,N次交换,每次只会改变两个元素的值
- 比较平均,与初始序列无关,没有最好最坏
2. 插入排序
2.1 基本思想
将一个数据插入到已经排好序的有序数据中。
从后往前找,当插入元素<第n个元素时,交换二者,直到插入元素>=第n个元素
2.2 性能分析
- 最坏情况:逆序
- 比较次数:1+2+……+N-1=N(N-2)~ N2/2
- 交换次数:1+2+……+N-1=N(N-2)~ N2/2
- 最好情况:有序
- 比较次数:N-1,每次插入只需要一次比较
- 交换次数:0
2.3 特点
- 需要给插入元素腾出空间,将插入位置之后的元素右移。实际中为,每次比较,都一次交换
- 需要初始顺序有关,部分有序的数组比随机数组快的多
3. 希尔排序
3.1 基本思想
- 基于插入排序,交换不相邻元素,对数组局部进行排序,并最终用插入排序将局部有序的数组排序。
- 使数组中间隔为h的元素都是有序的。h-子数组中交换到比它大的元素之前去,只需要将插入排序代码移动元素的距离由1改为h即可。
3.2 性能分析
- 透彻理解希尔排序的性能至今仍然是一项挑战。达不到平方级别,最坏情况下,比较次数与N^(3/2)成正比
- 不需要额外的空间
3.3 特点
- 间隔序列的选择会影响排序效率
- 排序之初,各子数组很短,排序之后各子数组部分有序。两种情况都适合插入排序
4. 归并排序
4.1 算法思想
- 将两个有序数组,归并成一个更大的有序数组。
- 原地归并:需要一个辅助数组,i,j分别作为两个数组的哨兵。a[i]?a[j],第一个数组的第i个元素小,则将该元素放入辅助数组,i++;同理。直到其中一个数组的元素用尽,即i>mid或j>hi,则直接取另外一个数组的元素,直至全部用尽。
4.2 性能分析
- 递归实现和非递归实现,都需要1/2NlgN至NlgN次比较
- 一个长度为N的辅助数组
- 最坏情况需要NlgN次比较
4.3 特点
- 最坏情况下,归并排序最好
- 空间复杂度不是最优
5. 快速排序
5.1 算法思想
- 分治思想:将一个数组分成两个子数组,将两部分独立地排序。
- 切分:切分元素的位置排定,之前的所有元素不大于它,之后所有元素不小于它。两个指针头指针i,尾指针j,从左往右扫描数组,直到找到大于等于切分元素的a[i],从右往左扫描数组,直到找到小于等于切分元素的a[j],交换a[i]和a[j]的位置,直到指针i和j相遇。
5.2 性能分析
最好情况是切分元素每次都能把数组对半分,此时比较次数为NlgN
最坏情况是切分不平衡,第一次从最小元素切分,第二次从第二小的元素切分,此时比较次数约
N2/2
空间复杂度lgn(递归辅助栈)
5.3 特点
- 实现简单,运用广泛
- 原地排序(只需要一个很小的递归辅助栈)
- 与初始序列(切分元素的顺序)有关
- 缺点是非常脆弱,很容易达到最坏情况,平方级别的时间复杂度
6. 堆排序
6.1 算法思想
- 数组实现的二叉堆,二叉树的每个节点都大于等于两个子结点,按层级顺序放入数组,位置k个父节点为k/2,两个子结点分别为2k,2k+1
- 所有元素插入最小堆,再重复调用删除最小元素的操作,按顺序删去。
- 将排序的数组作为堆本身,无需额外空间
6.2 性能分析
唯一能够同时最有利用空间和时间的方法,最坏情况下~2NlgN次比较
6.3 特点
- 无法利用缓存,很少和相邻的其他元素进行比较,缓存未命中次数远远高于其他算法
总结:
- 任何一个基于比较的排序算法,比较次数都大于等于NlgN
- 稳定的:冒泡排序、插入排序和归并排序,其他都不稳定。
- 逆序时达到最坏情况:插入排序,快速排序
- 顺序时达到最坏情况:快速排序
- 找n个数的中位数,可以在O(n)时间内完成
- 最好情况最快的是插入排序比较次数为N-1