经典排序算法

排序算法分类

(一)

  • 内部排序和外部排序

(二)

  1. 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。(非线性时间)
  2. 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。 (线性时间)

(三)

  1. 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序。如:快速排序、归并排序、堆排序、冒泡排序等。在排序的最终结果里,元素之间的次序依赖于它们之间的比较。每个数都必须和其他数进行比较,才能确定自己的位置。
  2. 线性时间非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此称为线性时间非比较类排序。如:计数排序、基数排序、桶排序。非比较排序是通过确定每个元素之前,应该有多少个元素来排序。针对数组arr,计算arr之前有多少个元素,则唯一确定了arr在排序后数组中的位置。

(四)

  1. 比较类排序
    • 交换排序 (swap)
      • 冒泡排序 (bubble Sort) - 双重遍历,相邻元素两两比较交换
      • 快速排序 (quick Sort) - 较复杂
    • 插入排序 (insertion)
      • 简单插入排序 (insertion sort) - 分左右两批,遍历有序列表,将无序的元素插入有序的列表
      • 希尔排序 (shell sort) (缩小增量排序) - 较复杂
    • 选择排序 (selection)
      • 简单选择排序 (selection) - 双重遍历,每次找到最小的元素,最后和该趟遍历的第一个元素进行交换
      • 堆排序 (heap sort)
    • 归并排序 (merge sort) - 即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。 (递归)
      • 二路归并排序
      • 多路归并排序
  2. 非比较类排序
    • 计数排序 (counting sort)
    • 桶排序 (bucket sort)
    • 基数排序 (radix sort)(分配排序)

(五)

  • 算法复杂度
排序方法 时间复杂度(平均) 时间复杂度(最坏) 时间复杂度(最好) 空间复杂度 稳定性
冒泡排序 O(n^2) O(n^2) O(n) O(1) 稳定
快速排序 O(nlog2n) O(n^2) O(nlog2n) O(nlog2n) 不稳定
简单插入排序 O(n^2) O(n^2) O(n) O(1) 稳定
希尔排序 O(n1.3) O(n^2) O(n) O(1) 不稳定
简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
堆排序 O(nlog2n) O(nlog2n) O(nlog2n) O(1) 不稳定
归并排序 O(nlog2n) O(nlog2n) O(nlog2n) O(n) 稳定
计数排序 O(n+k) O(n+k) O(n+k) O(n+k) 稳定
桶排序 O(n+k) O(n^2) O(n) O(n+k) 稳定
基数排序 O(n*k) O(n*k) O(n*k) O(n+k) 稳定
  • 相关概念:

1、时间复杂度

  • 时间复杂度可以认为是对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
  • 常见的时间复杂度有:常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2)
  • 时间复杂度O(1):算法中语句执行次数为一个常数,则时间复杂度为O(1),

2、空间复杂度

  • 空间复杂度是指算法在计算机内执行时所需存储空间的度量,它也是问题规模n的函数
  • 空间复杂度O(1):当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1)
  • 空间复杂度O(log2N):当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为O(log2n), ax=N,则x=logaN,
  • 空间复杂度O(n):当一个算法的空间复杂度与n成线性比例关系时,可表示为0(n).

复杂度分析

  • 常见排序算法分类(排序算法,是算法的基石,你掌握多少?)
  • 大O时间复杂度表示法:表示代码执行时间随数据规模增长的变化趋势,又称渐进时间复杂度
  • 大O空间复杂度表示法:表示代码执行所占的内存空间随数据规模增长的变化趋势,又称渐进空间复杂度
  • 复杂度分析法则
    • 单段代码,看循环的次数。
    • 多段代码,看代码循环量级。
    • 嵌套代码求乘积,比如递归和多重循环。
    • 多个规模求加法,方法中并行的两个循环。
  • 常用的复杂度级别
    • 多项式阶:随着数据规模的增长,算法的执行时间和空间占用,按照多项式的比例增长,包括,O(1)(常数阶)、O(logn)(对数阶)、O(n)(线性阶)、O(nlogn)(线性对数阶)、O(n2)(平方阶)、O(n3)(立方阶)。
    • 非多项式阶:随着数据规模的增长,算法的执行时间和空间占用暴增,这列算法性能极差。包括,O(2^n)(指数阶)、O(n!)(阶乘阶)

(六)

  • 稳定性
  • 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,A1=A2,且A1在A2之前,而在排序后的序列中,A1仍在A2之前,则称这种排序算法是稳定的;否则称为不稳定的。
  • 稳定也可以理解为一切皆在掌握中,元素的位置处在你在控制中.而不稳定算法有时就有点碰运气,随机的成分.当两元素相等时它们的位置在排序后可能仍然相同.但也可能不同.是未可知的.
  • 不稳定排序算法
    • 快选希堆(快速排序,选择排序,希尔排序,堆排序)

(七)

  • 算法总结
  • 所需辅助空间最多:归并排序;
    所需辅助空间最少:堆排序;
    平均速度最快:快速排序;
    不稳定:快速排序,希尔排序,堆排序。

冒泡排序

  • 1、冒泡排序是一种用时间换空间的排序方法,n小时好
  • 2、最坏情况是把顺序的排列变成逆序,或者把逆序的数列变成顺序,最差时间复杂度O(N^2)只是表示其操作次数的数量级
  • 3、最好的情况是数据本来就有序,复杂度为O(n)

快速排序

  • 1、n大时好,快速排序比较占用内存,内存随n的增大而增大,但却是效率高不稳定的排序算法。
  • 2、划分之后一边是一个,一边是n-1个,
    这种极端情况的时间复杂度就是O(N^2)
  • 3、最好的情况是每次都能均匀的划分序列,O(N*log2N)

归并排序

  • 1、n大时好,归并比较占用内存,内存随n的增大而增大,但却是效率高且稳定的排序算法。

Reference