Processing math: 100%

MIT 6006 Lecture 7——计数排序,基数排序,排序的时间复杂度下界

AVL树——一种平衡的BST

课程内容

  • 比较模型
  • 时间复杂度下界
    • 搜索:Ω(lgn)
    • 排序:Ω(nlgn)
  • O(n)时间复杂度的排序
    • 计数排序
    • 基数排序

比较模型

定义

  • 所有输入对象均为黑盒(抽象数据结构)
  • 唯一允许的操作是比较操作(<,,>,,=
  • 时间损耗只和比较操作的次数有关

决策树

任何的比较操作,实际上都可以视为一棵树,这棵树由可能的路径和结果构成。例如,二分查找可以被视为一颗二分查找树。下面给出了一个二分查找的过程,在长度n=3的数组里进行二分查找:

算法和树的对应关系如下:

决策树 算法
内部节点 二分决策(比较)
叶节点 结果
根到叶的路径 一次算法的执行
路径长度 算法的执行时间
树高 最坏执行时间

时间复杂度下界

搜索的时间复杂度下界

n经过处理(排序或其他操作)的对象中,根据比较模型找到一个指定的目标,最坏情况下时间复杂度下界为Ω(lgn)

证明

  • 首先,我们的决策树是一个二叉树,同时,这棵树至少有n个节点,每个节点对应一个解
  • 所以树的高度hlgn,证明完毕

排序的时间复杂度下界

在搜索算法中,我们证明了Ω=lgn,即从n个对象中找到一个解的时间复杂度下界为lgn,那么直观来看,如果我们要排序,就是从n个元素中找到n个解,这n个解分别为第一大元素、第二大元素、…、第n大元素,所以时间复杂度应为nlgn

证明

首先,对于这个排序问题,我们的决策树依旧是一个二叉树,所以我们要看一下这个树有多少个节点。对于排序问题,我们的一个节点也是一个解,这个解是一个排序序列,例如:

A[5]A[7]A[10]A[2]...A[3]

那么有多少个节点呢,根据排列组合,所有可能的情况为Ann=n!n factorial),则树高h满足

hlg(n!)

我们现在要证明lg(n!)nlgn,证明过程如下:

lg(n!)=lg(n(n1)(n2)...(2)(1))=lg(n)+lg(n1)+...+lg(2)+lg(1)ni=n/2lg(i)ni=n/2lgn2=ni=n/2(lgn1)=n2(lgn1)=Ω(nlgn)

线性时间排序

假设我们的待排序的对象是整数,那么我们可以制造出一些整数排序的结果,我们先进行一些假设:

  • 假设key是整数,且key0,1,2,,k1,同时一个key的长度小于计算机的一个字
  • 不止可以进行比较操作,还可以进行别的操作
  • 对于k,可以在O(n)时间复杂度下进行排序

目前来说,最好的排序算法能够达到的时间复杂度为O(n(lgnlgn))

计数排序

配置一个计数器,然后遍历数组,每遇到一个元素,就将对应的key所在的位置+1,然后遍历计数器,进行排序。计数排序中一个比较重要的问题是考虑排序的稳定性,如果我们要保证相同元素排序后位次不变,那么可以使用如下算法:

1
2
3
4
5
6
L = array of k empty lists      O(k)
for i in range(n): O(n)
L[key(A[j])].append(A[j]) O(1)
output = []
for i in range(k) O(n+k)
output.extend(L[i]) O(|li|)

所以计数排序的时间复杂度为O(n+k),如果k很大,那么性能很差。

基数排序

基数排序基于计数排序,其基本原理是使用对数缩小数的范围,然后再利用计数排序进行排序

  • 同样假设key为整数,令其表示为以b为底的对数,即d=logbk
  • 然后我们的key的范围变成了0d

实际上是进行了一次分组操作,对于一组进行计数排序,需要O(n+b)次操作;而对于全部,则需要O((n+b)d)=O((n+b)logbk)

可以证明,当b=n时,时间复杂度最小,为O(nlognk)=O(nc)

参考文献

0%