《算法导论》第六章 -- 堆,堆排序(含习题)

  堆,一般是指二叉堆,是指如下的数据结构

在这里插入图片描述

  将一个数组上的元素从头到尾按照从左向右、从上向下的方式填到一颗二叉树上,就是一个堆。一个最大/小堆表示满足父节点总是大于/小于子节点的堆。

堆用于排序的思想

  因为堆上的很多操作只需要 l g n lgn lgn的时间(包括从一个最大/小堆上取出最大/小值,然后重整堆使其满足最大/最小性质),所以堆可以用于在 O ( n l g n ) O(nlgn) O(nlgn)时间内进行排序。
  但是我认为堆最大的用处不在于排序, 而是在于堆维护自己的堆性质的操作基本上只需要 l g n lgn lgn的执行时间,当需要对某个序列上的元素的key值进行频繁的改动,并经常需要根据key值堆序列进行排序的时候,堆是非常好的数据结构。

堆的重要性质

  堆最重要的性质是最大/小堆的父节点一定大于/小于每一个子节点,同时堆的深度是 l g n lgn lgn。该性质导致包括排序在内的很多操作只需要很小的时间复杂度。同时,当修改了一个节点上key的值的时候,堆也只需要画很小的时间复杂度就可以重新拥有堆的性质。
  对一个最大堆,当减小了一个节点的key的值(或者不知道这个节点的key的值是否大于子节点的key值时)调用MAX-HEAPIFY方法可以在 O ( h i ) O(h_i) O(hi)时间内重整堆,该算法假设其他所有节点都已经满足堆的性质,所以只需要不停的将本节点和最大的子节点互换位置直到本节点满足堆性质( h i h_i hi表示该节点的高度)。当增加一个节点的key的值的时候(同样假设其他节点已经满足堆的性质),可以不断比较该节点父节点的key值,并在违反堆性质时互换节点和父节点的位置来在 O ( d i ) O(d_i) O(di)时间内重整堆。 d i d_i di表示该节点距离根节点的深度。可以看到 d i , h i d_i,h_i di,hi都是 O ( l g n ) O(lgn) O(lgn)的。也就是说,对于一个所有节点都满足堆性质的堆,增加/减少一个节点的key值可以在 l g n lgn lgn的时间内重整堆,使得该堆每个节点满足堆性质。
  总的来说,单单从排序的角度来说,可以把堆看作排序的“前体”,这个前体最大的优势是可以在很短时间内响应任意节点的key值的修改。并且一个最大/小堆的排序可以达到比较排序的下限,即 O ( n l g n ) O(nlgn) O(nlgn).

堆的性质总结

  1. 从子节点找到父节点、从父节点找到子节点只需要常数时间
  2. 建立一个堆可以在 O ( n ) O(n) O(n)时间内完成
  3. 二叉堆在渐进意义上和完全二叉树相等,即堆要么是完全的,要么最大深度和最小深度差常数项(实际上就是1)
  4. 大部分堆上的操作和堆的深度成线性关系 O ( h ) O(h) O(h),而深度和容量成lg关系 h = l g ( n ) h = lg(n) h=lg(n)
  5. 高度为h的堆,其容量 n ∈ [ 2 h , 2 h + 1 − 1 ] n \in [2^h, 2^{h+1}-1] n[2h,2h+11]
  6. 含n个元素的堆,其高度为 ⌊ l g n ⌋ \lfloor lgn \rfloor lgn
  7. 叶节点的下标从 ⌊ n / 2 ⌋ + 1 \lfloor n/2 \rfloor+ 1 n/2+1 n n n
  8. 对于一个大小为n的堆, MAX/MIN-HEAPIFY和INCREASE-KEY (最大堆)/DECREASE-KEY(最小堆)最差情况下需要调用 l g n lgn lgn次数,故其时间复杂度是 Ω ( l g n ) \Omega(lgn) Ω(lgn)
  9. 任意一个包含n个元素的堆,其深度为 h h h的节点数总是小于 ⌈ n / 2 h + 1 ⌉ \lceil n/2^{h+1} \rceil n/2h+1的。
  10. 在所有元素都不同的情况下,堆排序算法是 Ω ( n l g n ) \Omega(nlgn) Ω(nlgn)的。(当考虑重复元素时,准确进行堆排序的算法分析开始变得困难)

优先队列

  除了排序外,堆的性质而可以用来实现其他的一些非常有用的数据结构比如优先队列。除了维护堆性质的算法外,优先队列实现了以下算法

  1. MAX/MIN 在 O ( 1 ) O(1) O(1)<
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值