排序相关总结(复杂度、稳定性、比较)

排序的稳定性:

这个东西,自己也有点理解不清楚,这里作个总结。

先看概念:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。

看到重点,是看相同的关键字,然后再是相对次序。。之前一直看东西看一半,看到个相对次序,所以一脸懵逼。


然后再是常见算法的稳定性记录:

稳定的:

基数排序:(筒子法排序,例如,先针对个位排序,然后针对十位排序,如此)

冒泡排序:(但是,也可以通过改变冒泡的写法, 让他不稳定)

直接插入排序:取一个数,看看他在有序的哪个位置吗,放进去,如此

折半插入排序:思想一样,就是查这个位置的时候,用二分

归并排序:1分2,2分4,4分万物,最后有序合并

不稳定的:

堆排序:可能在建堆的时候,就发生了不稳定的情况(比如分到两个二叉树了之类的)

快速排序:选择基准很重要,有可能造成不稳定

希尔排序:是插入排序的一种(希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止)(因为一次插入排序是稳定的,多次,尤其在合并的过程中,可能会发生交换)

直接选择排序:因为会跨域交换,因此会不稳定


排序算法的复杂度


此图来自:http://blog.csdn.net/yuxin6866/article/details/52771739(这个图的辅助存储我表示怀疑,可以不看)


算法的比较

exp1:堆排序是渐进最优的比较排序算法,达到了O(nlgn)这一下界,而快排有一定的可能性会产生最坏划分,时间复杂度可能为O(n^2),那为什么快排在实际使用中通常优于堆排序?

楼上几位说的不全,补充一下,堆排比较的几乎都不是相邻元素,对cache极不友好,这才是很少被采用的原因。
数学上的时间复杂度不代表实际运行时的情况

这里的关键问题就在于第2步,堆底的元素肯定很小,将它拿到堆顶和原本属于最大元素的两个子节点比较,它比它们大的可能性是微乎其微的。实际上它肯定小于其中的一个儿子。而大于另一个儿子的可能性非常小。于是,这一次比较的结果就是概率不均等的,根据前面的分析,概率不均等的比较是不明智的,因为它并不能保证在糟糕情况下也能将问题的可能性削减到原本的1/2。可以想像一种极端情况,如果a肯定小于b,那么比较a和b就会什么信息也得不到——原本剩下多少可能性还是剩下多少可能性。

在堆排里面有大量这种近乎无效的比较,因为被拿到堆顶的那个元素几乎肯定是很小的,而靠近堆顶的元素又几乎肯定是很大的,将一个很小的数和一个很大的数比较,结果几乎肯定是“小于”的,这就意味着问题的可能性只被排除掉了很小一部分。

这就是为什么堆排比较慢(堆排虽然和快排一样复杂度都是O(NlogN)但堆排复杂度的常系数更大)


归并排序和快速排序

归并的话,辅助空间多,也相对更复杂


最后提一下,稳定性

假设有一序列,需要先按第一关键字排序,第一关键字相同的可以按第二关键字排序。
那么处理方法可以这样:先按第二关键字排序,再按第一关键字稳定排序,目的就达到了。非稳定关键字排序则不行

题目也可以这样描述,原来是按第二关键字排序,现在要改为按第一关键字排序。但希望第一关键相同的元素次序不便。资源管理器,先按时间排序,再按类型排序,就是这样的需求。


这个例子还算形象,好像是,在对象的排序里面,稳定性的意义才会体现出来。

你可能感兴趣的:(码农基础之路)