算法导论(6)

  • 待排序的项称为 记录 (record),每个记录包含一个 关键字 (key),即排序问题中要重排的值,记录的剩余部分由 卫星数据 (statellite data)组成。
  • 如果输入数组中仅有常数个元素需要在排序过程中存储在数组之外,则称排序算法是 原址的 (in place)。插入排序可以在$\Theta(n^2)$时间内将n个数排好序,是一种非常快的原址排序算法;归并排序有更好的渐近运行时间$\Theta(n\lg n)$,但它使用的MERGE过程并不是原址的。
算法 最坏情况运行时间 平均情况/期望运行时间
插入排序 $\Theta(n^2)$ $\Theta(n^2)$
归并排序 $\Theta(n\lg n)$ $\Theta(n\lg n)$
堆排序 $O(n\lg n)$
快速排序 $\Theta(n^2)$ $\Theta(n\lg n)$(期望)
计数排序 $\Theta(k+n)$ $\Theta(k+n)$
基数排序 $\Theta(d(n+k))$ $\Theta(d(n+k))$
桶排序 $\Theta(n^2)$ $\Theta(n)$(平均情况)

堆排序

算法 时间复杂度 空间原址性
插入排序 $O(n^2)$
归并排序 $O(n\lg n)$
堆排序 $O(n\lg n)$

  • 计算父节点、左右孩子节点下标

    PARENT(i)
      return i/2
    LEFT(i)
      return 2i
    RIGHT(i)
      return 2i+1
    
    
  • 最大堆除了根以外的所有节点 i 满足:$A[\rm{PARENT}(i)]\geq A[i]$

  • 最小堆除了根以外的所有节点 i 满足:$A[\rm{PARENT}(i)]\leq A[i]$

  • 对于完全二叉树,叶节点数 = 非叶节点数 或 非叶节点数+1

维护堆的性质

MAX-HEAPIFY(A, i) 通过逐级下降,使得下标为 i 的根节点的子树符合最大堆的性质

MAX-HEAPIFY(A, i)
l = LEFT(i)
r = RIGHT(i)
if l <= A.heap-size and A[l] > A[i]
  largest = l
else
  largest = i
if r <= A.heap-size and A[r] > A[largest]
  largest = r
if largest != i
  exchange A[i] with A[largest]
  MAX-HEAPIFY(A, largest)

每个孩子的子树的大小最多为 $2n/3$(最坏情况发生在树的最底层半满的时候),故MAX-HEAPIFY运行时间 $T(n) \leq T(2n/3) + \Theta(1)$,解为$T(n) = O(\lg n)$。

建堆

BUILD-MAX-HEAP 把大小为 n = A.length 的数组 A[1..n] 转换为最大堆。

BUILD-MAX-HEAP(A)
    A.heap-size = A.length
    // 子数组 $A(n/2+1..n)$ 中的元素都是叶节点
    for i = A.length/2 downto 1
        MAX-HEAPIFY(A, i)
  • 渐近上界 BUILD-MAX-HEAP 需要调用MAX-HEAPIFY O(n) 次,故总的时间复杂度为 $O(n\lg n)$,或者$O(nh)$。
  • 更加紧确 含n个元素的堆高度为 $\lfloor \lg n\rfloor$,高度为h的元素数最多为 $\lceil n/2^{h+1} \rceil$,于是 BUILD-MAX-HEAP的时间复杂度为 $O\left( \sum_{h=0}^{\lfloor \lg n\rfloor} \lceil n/2^{h+1} \rceil O(h) \right) = O\left(n\sum_{h=0}^{\lfloor \lg n\rfloor}\frac{h}{2^h}\right) = O\left(n\sum_{h=0}^{\infty}\frac{h}{2^h}\right) = O(n)$

堆排序算法

HEAPSORT(A)
  BUILD-MAX-HEAP(A)
  for i = A.length downto 2
    exchange A[1] wiith A[i]
    A.heap-size = A.heap-size - 1
    MAX-HEAPIFY(A, 1)

MAX-HEAPIFY 时间复杂度为 $O(\lg n)$,被HEAPSORT n-1 次调用,故 HEAPSORT 的时间复杂度为 $O(n\lg n)$

优先队列

  • 优先队列 是一种用来维护由一组元素构成的集合S的数据结构,每个元素有一个相关的值,称为 关键字 (key)。优先队列同样有两种形式: 最大优先队列 和 最小优先队列 。
  • 一个最大优先队列支持以下操作:
    • INSERT(S, x):把元素x插入集合S中。
    • MAXINUM(S):返回S中具有最大关键字的元素。
    • EXTRACT-MAX(S):去掉并返回S中具有最大关键字的元素。
    • INCREASE-KEY(S, x, k):将元素x的关键字值加到k
  • 最大优先队列用于共享计算机系统的作业调度,最小优先队列用于基于事件驱动的模拟器(关键字为事件发生时间)。
HEAP-MAXINUM(A)
  return A[1]
HEAP-EXTRACT-MAX(A)
  if A.heap-size < 1
    error "heap underflow"
  max = A[1]
  A[1] = A[A.heap-size]
  A.heap-size = A.heap-size - 1
  MAX-HEAPIFY(A, 1)
  return max

HEAP-EXTRACT-MAX 的时间复杂度为 $O(\lg n)$(取决于MAX-HEAPIFY的时间复杂度)。

HEAP-INCREASE-KEY(A, i, key)
  if key < A[i]
    error "new key is smaller than current key"
  A[i] = key
  while i > 1 and A[PARENT(i)] < A[i]
    exchange A[i] with A[PARENT(i)]
    i = PARENT(i)

HEAP-INCREASE-KEY 中当前元素不断与父元素比较,当前元素大则将二者交换,直至当前元素的关键字小于父节点。时间复杂度为$O(\lg n)$。

MAX-HEAP-INSERT(A, key)
    A.heap-size = A.heap-size + 1
    A[A.heap-size] = - MAX_INT
    HEAP-INCREASE-KEY(A, A.heap-size, key)

MAX-HEAP-INSERT的时间复杂度为$O(\lg n)$。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值