常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较

先看表格

分类 算法 时间复杂度 空间复杂度       稳定性           关联性       
最好          最差        平均      
插入排序        直接插入排序      O(n)(优化后)     O(n2)           O(n2)           O(1) 稳定  
希尔排序 O(n) O(n2) 不确定 O(1) 不稳定 基于直接插入排序    
选择排序 简单选择排序 O(n2) O(n2) O(n2) O(1) 不稳定  
堆排序 O(nlogn) O(nlogn) O(nlogn)

就地排序-O(1)   

不稳定 应用了选择的理念
交换排序 冒泡排序 O(n)(优化后) O(n2) O(n2) O(1) 稳定  
快速排序 O(nlogn) O(n2) O(nlogn)

最好O(logn),

最差O(n) 

不稳定 基于冒泡排序
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定  
基数排序

O(d*(n+r))

d是位数,r是基数,

n是比较的数目

O(d*(n+r)) O(d*(n+r)) O(n+r) 稳定  

插入排序----直接插入排序(Straight Insertion Sort)

(1)基本思想: 将一个记录插入到已排序好的有序表中,从而得到一个新的,记录数增1得有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
(2) 优缺点: 优点:稳定、快; 缺点:比较次数不一定,比较次数越少,插入点后的数据移动越多,数据量庞大的时候不是很友好

常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较
如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

插入排序----希尔排序(Shell`s Sort)

背景:希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进。希尔排序又叫缩小增量排序
**(1)基本思想:**先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
(2) 适用场景: 比较在希尔排序中是最主要的操作,而不是交换。用已知最好的步长序列的希尔排序比直接插入排序要快,甚至在小数组中比快速排序和堆排序还快,但在涉及大量数据时希尔排序还是不如快排;

选择排序----简单选择排序(Simple Selection Sort)

(1)基本思想: 在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
(2) 示意图:
常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较

选择排序----堆排序(Heap Sort)-----了解即可

(1)基本思想: 堆的定义如下:具有n个元素的序列(k1,k2,…,kn),当且仅当满足
常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较
时称之为堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最小项(小顶堆)。
若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的。如:

(a)大顶堆序列:(96, 83,27,38,11,09)

(b) 小顶堆序列:(12,36,24,85,47,30,53,91)
常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较

初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。称这个过程为堆排序。

交换排序----冒泡排序(Bubble Sort)

(1)基本思想: 在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现他们的排序与排序要求相反时,就将他们互换。
(2) 示意图:
常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较
(3) 优缺点: 优点:稳定; 缺点:慢,每次只能移动两个相邻的数据

交换排序----快速排序(Quick Sort)---- 重点

(1) 基本思想: 选择一个基准元素,将比基准元素小的元素放在其前面,比基准元素大的元素放在其后面,然后在将小于基准值元素的子数列和大于基准元素的子数列按原来的方法排序,直到整个序列有序;
(2) 优缺点: 优点:速度极快数据移动少; 缺点:不稳定;
(3) 效率分析: 此排序算法的效率在序列越乱的时候,效率越高。在数据有序时,会退化成冒泡排序;对于每一次的基准的选择也至关重要
(4) 示意图
(a)一趟排序的过程
常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较
(b) 排序的全过程
常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较

归并排序(Merge Sort)

(1) 基本思想: 首先将初始序列的n个记录看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2的有序子序列,在此基础上,再对长度为2的有序子序列进行两两归并,得到若干个长度为4的有序子序列,以此类推,直到得到一个长度为n的有序序列为止;
(2) 使用场景: 若n较大,并且要求排序稳定,则可以选择归并排序;
(3) 示意图
常见排序算法的最好、最坏、平均时间复杂度、稳定性、是否基于比较

桶排序/基数排序(Radix Sort)---- 了解即可

(1) 基本思想 是将阵列分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的阵列内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
简单来说,就是把数据分组,放在一个个的桶中,然后对每个桶里面的在进行排序。
例如要对大小为[1…1000]范围内的n个整数A[1…n]排序

首先,可以把桶设为大小为10的范围,具体而言,设集合B[1]存储[1…10]的整数,集合B[2]存储 (10…20]的整数,……集合B[i]存储( (i-1)10, i10]的整数,i = 1,2,…100。总共有 100个桶。

然后,对A[1…n]从头到尾扫描一遍,把每个A[i]放入对应的桶B[j]中。 再对这100个桶中每个桶里的数字排序,这时可用冒泡,选择,乃至快排,一般来说任 何排序法都可以。

最后,依次输出每个桶里面的数字,且每个桶中的数字从小到大输出,这 样就得到所有数字排好序的一个序列了。

假设有n个数字,有m个桶,如果数字是平均分布的,则每个桶里面平均有n/m个数字。如果

对每个桶中的数字采用快速排序,那么整个算法的复杂度是

O(n + m * n/m*log(n/m)) = O(n + nlogn - nlogm)

从上式看出,当m接近n的时候,桶排序复杂度接近O(n)

当然,以上复杂度的计算是基于输入的n个数字是平均分布这个假设的。这个假设是很强的 ,实际应用中效果并没有这么好。如果所有的数字都落在同一个桶中,那就退化成一般的排序了。

前面说的几大排序算法 ,大部分时间复杂度都是O(n2),也有部分排序算法时间复杂度是O(nlogn)。而桶式排序却能实现O(n)的时间复杂度。但桶排序的缺点是:

1)首先是空间复杂度比较高,需要的额外开销大。排序有两个数组的空间开销,一个存放待排序数组,一个就是所谓的桶,比如待排序值是从0到m-1,那就需要m个桶,这个桶数组就要至少m个空间。

2)其次待排序的元素都要在一定的范围内等等。

桶式排序是一种分配排序。分配排序的特定是不需要进行关键码的比较,但前提是要知道待排序列的一些具体情况。


相关记忆技巧

1.关于稳定性

不稳定:快选堆希(快速排序、选择排序、堆排序、希尔排序)
稳 定: 插冒归计基 (简单插入排序、冒泡排序、归并排序、计数排序、基数(桶)排序)

2.是否基于比较

比较:插入排序、选择排序、归并排序、快速排序、堆排序
非比较:基数排序、计数排序、桶排序

具体实现可以参考:代码实现参考Blog就很牛逼