各种排序算法的复杂度和稳定性
名称 | 数据对象 | 稳定性 | 时间复杂度 | ?? | 空间复杂度 | 描述 |
?? | ?? | ?? | 平均 | 最坏 | ?? | ?? |
数组 | ?? | (无序区,有序区)。从无序区通过交换找出最大元素放到有序区前端。 | ||||
数组 | ?? | (有序区,无序区)。在无序区里找一个最小的元素跟在有序区的后面。对数组:比较得多,换得少。 | ||||
?? | 链表 | ?? | ?? | ?? | ?? | |
数组、链表 | ?? | (有序区,无序区)。把无序区的第一个元素插入到有序区的合适的位置。对数组:比较得少,换得多。 | ||||
数组 | ?? | (最大堆,有序区)。从堆顶把根卸出来放在有序区之前,再恢复堆。 | ||||
数组 | ?? |
,如果不是从下到上 | 把数据分为两段,从两段中逐个选最小的元素移入新数据段的末尾。可从上到下或从下到上进行。 | |||
?? | 链表 | ?? | ?? | ?? | ?? | |
数组 | (小数,枢纽元,大数)。 | |||||
数组 | 每一轮按照事先决定的间隔进行插入排序,间隔会依次缩小,最后一次一定要是1。 | |||||
数组、链表 | ?? | 统计小于等于该元素值的元素的个数i,于是该元素就放在目标数组的索引i位(i≥0)。 | ||||
数组、链表 | ?? | 将值为i的元素放入i号桶,最后依次把桶里的元素倒出来。 | ||||
数组、链表 | ?? | 一种多关键字的排序算法,可用桶排序实现。 |
? ?
平均时间复杂度由高到低为:
冒泡排序O(n2)
选择排序O(n2)
插入排序O(n2)
希尔排序O(n1.25)
堆排序O(n log n)
归并排序O(n log n)
快速排序O(n log n)
基数排序O(n)
? ?
复杂度分析
? ?
直接插入排序,冒泡排序,选择排序等双循环的都是n^2
归并,快排,堆排等带有递归的是nlogn
? ?
基于比较的排序算法的下限都是O(nlogn)
? ?
快排的过程:
取数组第一个元素设置为vot,然后从后到前查找小于vot的值,然后交换,再从前向后查找大于vot的值交换,第一遍结束后,分vot在数组中间,然后递归处理左右子数组就行了
? ?
插入,冒泡是稳定的
? ?
快排,堆排是不稳定的
? ?
归并是稳定的
? ?
选择排序是不稳定的
? ?
稳定性解释:
? ?
(1)冒泡排序
? ?
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
? ?
(2)选择排序
? ?
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
? ?
(3)插入排序
? ?
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
? ?
(4)快速排序
? ?
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。
? ?
(5)归并排序
? ?
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。
? ?
(8)堆排序
? ?
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n/2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法
? ?
摘自
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。