十大排序算法

八种常见的排序算法的代码实现,各算法的时间复杂度和空间复杂度,各自的优缺点,以及应用场景。

八种排序算法包括:选择排序,插入排序,希尔排序,冒泡排序,快速排序,归并排序,堆排序,基数排序。

2022-04-05:新增桶排序和计数排序。

Github地址:https://github.com/zhenruyi/SortingAlgos

实现语言:Golang。


0 代码实现

八种排序算法的代码实现


1 选择排序

算法原理
  • 首先在数组中找到最小的元素,将该元素和数组第一个元素交换位置;
  • 依次从剩余数组元素中找到最小的,放到剩余的数组范围开头位置;
  • 重复上一步,直到所有元素排序完毕。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n^2)

    • 最坏的情况:O(n^2)

    • 平均:O(n^2)

  • 空间复杂度:O(1),in-place

  • 不稳定:如果两个元素相等,先被选择的是后面的元素,所以后面的元素会被放到更前面。

优缺点
  • 优点
    • 简单
    • 移动次数已知:n-1
  • 缺点
    • 慢,比较次数多
应用场景

当数据规模较小时,选择排序性能较好。


2 插入排序

算法原理
  • 从数组的第二个元素开始,如果前一个元素比该元素大,则交换元素位置,即把该元素插入到适合的位置上;
  • 从头到尾,把所有的元素插入到适当的位置;
  • 如果该元素与前面某个元素相等,则插在其后面。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n)

    • 最坏的情况:O(n^2)

    • 平均:O(n^2)

  • 空间复杂度:O(1),in-place

  • 稳定:算法原理第三点。

优缺点
  • 优点
    • 简单,稳定
  • 缺点
    • 比较次数不一定,比较次数越少,插入点后的数据移动越多
应用场景

基本有序且数据规模较小时,选用插入排序较好。


3 希尔排序

算法原理
  • (对插入排序的改进,数组越大,优势越大。)
  • 选择一个间隔 interval = 3 * interval + 1 (1, 4, 13, 40, …);
  • 每轮interval /= 3。该轮中,间隔interval的元素均实行插入排序;
  • 当 interval = 1 时,整个数组当成一个组来处理,因为已经基本有序,所以比插入排序高效。
时间复杂度和空间复杂度
  • 时间复杂度:难以度量,O(n^(3/2))
  • 空间复杂度:O(1),in-place
  • 不稳定:interval不确定。
优缺点
  • 优点
    • 快,数据移动少
  • 缺点
    • 不稳定
应用场景

数据量较小且基本有序时。


4 冒泡排序

算法原理
  • 从第一个元素开始,比较相邻元素,如果第一个比第二个大,交换位置;
  • 对每一对相邻元素都这样操作,知道最大的元素到达数组尾;
  • 重复以上两个步骤,已经有序的元素不进行操作;
  • 直到所有元素都已经有序。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:我觉得是O(n^2),有说O(n)

    • 最坏的情况:O(n^2)

    • 平均:O(n^2)

  • 空间复杂度:O(1),in-place

  • 稳定:小于才交换,等于不交换。

优缺点
  • 优点
    • 简单
  • 缺点
    • 每次值移动相邻两个元素
应用场景

用于当数据已经基本有序,且数据量较小时。


5 快速排序

算法原理
  • (递归、分治)
  • 从数组中选取一个key,比key大的元素放在key右边,比key小的元素放在key左边;
  • 第一次的key选择为第一个元素,第一次排序好了后,以key为界分成两个数组;
  • 两个数组分别重复上面的步骤。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n log n)

    • 最坏的情况:O(n^2)

    • 平均:O(n log n)

  • 空间复杂度:O(log n)递归的深度,每次递归都会保存一些数据,in-place

  • 不稳定

优缺点
  • 优点
    • 已知最快的排序,数据移动少
  • 缺点
    • 不稳定,不适合对象排序
应用场景

快速排序适合处理大量数据排序时的场景。


6 归并排序

算法原理
  • (归并就是将两个有序的数组合并成一个有序的数组)
  • 将数组分成两个子数组,分别排序,最后归并;
  • 子数组内又分成两个数组,最后归并;
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n log n)

    • 最坏的情况:O(n log n)

    • 平均:O(n log n)

  • 空间复杂度:O(n),out-place

  • 稳定

优缺点
  • 优点
    • 稳定,适合对象排序
  • 缺点
    • 辅存很大
应用场景

数据量较大且要求排序稳定时。


7 堆排序

算法原理
  • 建立最大堆,把根节点和最后一个节点交换;
  • 重复上述步骤。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n log n)

    • 最坏的情况:O(n log n)

    • 平均:O(n log n)

  • 空间复杂度:O(1),in-place

  • 不稳定

优缺点
  • 优点
    • 最坏的条件下性能很优越,辅存少
  • 缺点
    • 不适合太小的序列,不稳定不适合对象排序
应用场景

堆排序适合处理数据量大的情况,数据呈流式输入时用堆排序也很方便。


8 基数排序

算法原理
  • 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n * k)

    • 最坏的情况:O(n * k)

    • 平均:O(n * k)

  • 空间复杂度:O(n + k),out-place

  • 稳定

优缺点
  • 稳定,快,但是空间复杂度大
应用场景

计数排序虽然时间复杂度较低,但需要满足的条件较多,如果能满足限制条件与空间需求,计数排序自然很快。


9 计数排序

算法原理
  • 找出数组中元素的最大值和最小值;
  • 新建一个计数字典,把数组元素的值作为key,等于这个值的元素的个数作为value;
  • 根据key从小到大遍历字典,将value个数的key放到数组中。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n + k)

    • 最坏的情况:O(n + k)

    • 平均:O(n + k)

  • 空间复杂度:O(k),out-place

  • 稳定

优缺点
  • 稳定,快,但是空间复杂度大
应用场景

计数排序虽然时间复杂度较低,但需要满足的条件较多,如果能满足限制条件与空间需求,计数排序自然很快。


10 桶排序

算法原理
  • 设置若干个桶,把符合的元素放入桶中;
  • 桶内排序;
  • 把结果复制回数组中。
时间复杂度和空间复杂度
  • 时间复杂度

    • 最好的情况:O(n + k)

    • 最坏的情况:O(n^2)

    • 平均:O(n + k)

  • 空间复杂度:O(n + k),out-place

  • 稳定

优缺点
  • 稳定,快,但是空间复杂度大
应用场景

如果满足桶排序的假设条件,即均匀分布,那么桶排序的速度是非常快的。


总结

  • 基于比较的排序算法
    • 简单排序:适用于数据量小的序列
      • 插入:基本有序时,性能比较好。O(n)
      • 选择:不稳定。当数据量很大时,选择排序性能会更好。
      • 冒泡:基本有序时,性能比较好。O(n)
    • nlogn时间复杂度
      • 快排:内部排序,对随机分布数据时间最短。不稳定。空间复杂度O(log n)。
      • 堆:空间复杂度比快排小O(1),没有快排的最坏情况。不稳定。
      • 归并:稳定,没有快排的最坏情况,但是空间复杂度为O(n)。
      • 希尔:最差情况多。
  • 线性时间排序算法:如果满足了线性时间排序算法的限制条件,使用线性时间排序将会使排序性能得到极大提升。
    • 计数排序:表现最好,只能处理范围内的正整数。
    • 桶排序:
    • 基数排序

参考

1.0 十大经典排序算法 | 菜鸟教程 (runoob.com)

Go排序算法及其性能比较 - 基数排序 - 《Go学习手册(For learning Go Tutorial)》 - 书栈网 · BookStack

排序算法总结 | 菜鸟教程 (runoob.com)

图解排序算法(三)之堆排序 - dreamcatcher-cx - 博客园 (cnblogs.com)

https://blog.csdn.net/Hairy_Monsters/article/details/80154391

https://blog.csdn.net/MBuger/article/details/67643185

(12条消息) 十大经典排序算法的复杂度分析_阿尔兹的博客-CSDN博客_排序算法复杂度