1. 冒泡排序
思路
冒泡排序是一种比较排序,且会交换元素位置。以从小到大排序为例,每轮排序过程会比较相邻两数大小,如果大数在前,则交换相邻两束位置,因此每轮将得到剩余元素中的最大值。
代码实现
1 | void bubble_sort(int arr[], int len) |
复杂度分析
最好情况下,数组已经排好序,仍需进行1轮的比较,时间复杂度为$O\left(n\right)$。最坏情况下,数组为倒序,总共需要$n^2$次比较,因此最坏时间复杂度为$O\left(n^2\right)$;平均时间复杂度为$O\left(n^2\right)$。
由于使用原数组进行元素交换排序,借用一个临时变量,因此时间复杂度为$O\left(1\right)$。
稳定性
使用交换元素进行排序,如果数相同,不会进行交换位置,因此冒泡排序为稳定排序。
2.选择排序
思路
选择排序是一种简单直观的排序算法,它的工作原理是首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
代码实现
1 | void selection_sort(int arr[], int len) |
复杂度分析
无论什么数据进去,都会进行进行$\frac{n\left(n-1\right)}{2}$次比较,因此时间复杂度无论最好最坏还是平均,都是$O\left(n^2\right)$。
由于只是借用临时变量来存储最小值索引和交换时所用的临时变量,因此空间复杂度为$O\left(1\right)$。
稳定性
选择排序是不稳定排序,例如5、8、5、2、9这个序列,第一次将第一个5和2交换,第一个5到了第二个5的后面。
3.插入排序
思路
插入排序的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。插入排序需要在有序表中查找合适的位置,通常从后往前扫描,找到相应的位置并插入。
代码实现
1 | void insert_sort(int arr[], int len) |
复杂度分析
最坏情况下数组逆序,需要比较$\frac{n\left(n - 1\right)}{2}$次,时间复杂度为$O\left(n^2\right)$。最好情况下,数组有序,只需要跟前一个元素比较一次,共$n-1$次,时间复杂度为$O\left(n\right)$。平均时间复杂度为$O\left(n^2\right)$。
空间复杂度为$O\left(1\right)$。
稳定性
由于比较用的是arr[pre] > temp,因此不会向左查询位置时,不会越过与自身相同的值,为稳定排序。
4. 希尔排序
思路
希尔排序可以说是对插入排序的一种改进,通过设置增量将序列分组进行插入排序。随着增量逐渐减少,每组包含的数越来越多,当增量减为1时,整个序列恰好被分成一组,算法便终止。增量为几,序列就被分成几组。下面来看一个具体的排序案例:
假设序列长度为len,我们设置增量gap的初值为len / 2,并以gap /= 2的方式减少增量形成一个增量序列:$\left(\frac{1}{2}len,\frac{1}{4}len,…,1\right)$。这里的除法为整除,舍弃余数部分。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。下面是整个过程:

代码实现
1 | void shell_sort(int arr[], int len) |
上述代码实现时,内部for循环i的初值设置为gap,是因为下标为gap的元素即第一组的第二个元素,插入排序一般从第二个元素开始。
复杂度分析
希尔排序最好情况下时间复杂度为$O\left(n\right)$,最坏情况下时间复杂度为$O\left(n^2\right)$。平均时间复杂度为$O\left(n^{1.3}\right)$。这里说的应该不一定指的是使用上述的增量序列的时间复杂度。
由于只是借助几个临时变量,且是在原数组上进行操作的,并未有额外的内存开销,因此空间复杂度为$O\left(1\right)$。
稳定性
由于通过增量进行分组并分别在组内排序,希尔排序为不稳定排序。
5. 归并排序
思路
归并排序采用分治法,将序列分成两份,对两个子序列分别排完序后进行归并。而子序列的排序采用同样的策略,直到子序列的长度为1。
代码实现
1 | void merge(int arr[], int bak[], int start, int end) |
复杂度分析
归并排序的时间复杂度无论是最好还是最坏情况下都是$O\left(nlogn\right)$。
由于需要借助额外的空间来存储中间过程,空间复杂度为$O\left(n\right)$。
稳定性
归并排序是稳定的。
未完待续….