● 每周一言
交流时,想说话之前最好先听清楚别人说的话。
导语
基本算法中最常用的算法,非排序莫属了。而现实生活中存在不少排序的例子,比如高矮站队需要排序,考试分数需要排序,整理卷子编号需要排序,等等。那么常用的排序算法有哪一些?它们分别如何实现的?
排序
排序算法的种类很多,从时间复杂度出发,可以有如下划分:
O(N)
:计数排序、桶排序、基数排序
O(NlogN)
:快速排序、堆排序、归并排序
O(N2)
:选择排序、插入排序、冒泡排序
时间复杂度和空间复杂度分别衡量的是程序运行所需的时间和内存占用,具体描述可参照《算法导论》。下面分别讲讲这九大排序算法。
计数排序 计数排序通过使用更多的存储空间来获得更快时间效率的排序方法。基本思想是以待排序数为数组下标存储计数,然后顺次输出,计数排序也因此得名。算法思想如下图所示,具体时间复杂度为
O(N+K)
。
桶排序 计数排序的最大问题是随着数据范围的扩大,空间复杂度也随之增加。而桶排序则是计数排序的进化版本,其并不是一对一的映射,而是通过一个映射函数一对多地把大小接近的数存到一个桶里,然后对每个桶中的序列再排序。算法思想如下图所示,具体时间复杂度为
∑iO(Ni∗logNi)
。
基数排序 上述两种方法较难解决混合数据的排序问题,比如字符串之间的排序。基数排序则是桶排序的升级版,基本思想是从低位到高位每轮均按位分桶。算法思想如下图所示,具体时间复杂度为
O(dN)
。
下面的排序算法采用的是比较法。
快速排序 快速排序的基本思想是每次确定序列中一个数的最终排序位置。算法思想如下图所示,具体时间复杂度为
O(NlogN)
。需要注意的是,遇到有序数列的时候,时间复杂度很可能退化到
O(N2)
,通常通过加入随机因子解决。
堆排序 堆排序的基本思想是先把序列构建成一个二叉最大或最小堆,然后每次移出堆顶的数,维持堆性质即可。构建一个二叉最小堆的过程如下图所示,具体时间复杂度为
O(NlogN)
。
归并排序 归并排序采用的是分而治之的思想,从局部有序到整体有序。算法思想如下图所示,具体时间复杂度为
O(NlogN)
。
选择排序 选择排序应该是最直观的排序算法了,基本思想是每一次选出剩余序列中的最大值或最小值。算法思想如下图所示,具体时间复杂度为
O(N2)
。
插入排序 插入排序的基本思想是顺次取出每个待排数插入到有序数列。算法思想如下图所示,具体时间复杂度为
O(N2)
。
冒泡排序 冒泡排序的基本思想是循环比较相邻的数,交换位置。算法思想如下图所示,具体时间复杂度为
O(N2)
。
以上基本已涵盖所有主流的排序算法。由于篇幅所限,具体代码细节实现就不在本文描述了。敬请期待下节内容 递归与分治。
结语
感谢各位的耐心阅读,后续文章于每周日奉上,欢迎大家关注小斗公众号 对半独白!