1. 基于比较的排序 这类排序包括插入,归并,堆,快速的等排序,共同点是都需要对数据进行比较,因此,时间复杂度不能突破O(NlogN),可以通过“二叉决策树模型”简单分析:
    • N个元素进行排序,最多有N!种排列方式
    • 决策树的根节点表示初始状态,可以认为有N!中不同可能方式,每个叶子节点是一种排序结果,所以最多有N!个叶子;
    • 非叶子节点是中间的一次比较;从根节点到叶子节点的每条路经代表一次排序过程;
    • 决策树的高度就对应了一次排序的比较次数(最差情况下);
    • 比较排序算法就可归结到二叉决策数深度问题;
    • 假设决策树高度为h,叶子节点个数最多为2^h,要求2^h>=N!,所以h>=log(N!),根据Stirling公式,log(N!)~O(Nlog(N)),所以,h>=O(Nlog(N))
    • 严重推荐 刘未鹏的一篇博文
  2. 非基于比较的排序 对输入数据有额外限制之后,可以使用一些时间复杂度更小的算法,如计数排序,桶排序,基数排序。
    1. 计数排序(Counting Sort)
      • 要求输入必须是在[0,n]之间的整数序列
      • 建立一个数组c=[0,n],初始化为0
      • 遍历输入序列,用c对出现的值进行计数
    2. 桶排序(Bucket Sort)
      • 额外的空间换取时间,可以看成对计数排序的改进和增强
      • 同样要求输入是上下界是可知的
      • 桶排序先按照输入的上下边界分成M个区间(桶),之后将输入放到对应的桶中,之后对每个桶进行排序(任意排序算法),之后搜集所有的桶内数据。
      • 时间复杂度是:O(n)+O(M)*O(N/M * log(N/M))=O(N+Nlog(N)-Nlog(M))
      • 可以看出,M越大,时间复杂度趋近O(N),但是空间复杂度变大(?)
      • 桶中的元素顺序存放则保证排序是稳定的
      • 桶排序基于一个假设:输入的数据由随机过程构成,否则在最坏情况下都分配到一个桶子里面,如果又不满足计数排序的假设要求,那么只能使用基于比较的排序算法进行排序,运行时间就退化到Ω(nlogn)。
    3. 基数排序(Radix sort)
      • 基数排序是在桶排序基础上的再次拓展,可以对多关键字进行排序
      • 假设我们有一些二元组(a,b),要对它们进行以a为首要关键字,b的次要关键字的排序。
      • 先按照首要关键字排序,分成首要关键字相同的若干堆。然后,在按照次要关键值分别对每一堆进行单独排序,最后再把这些堆串连到一起,使首要关键字较小的一堆排在上面。按这种方式的基数排序称为MSD(Most Significant Dight)排序。
      • 如果从最低有效关键字开始排序,称为LSD(Least Significant Dight)排序。
TOP