算法设计与分析——堆(一):基础知识

分类目录:《算法设计与分析》总目录
相关文章:
·堆(一):基础知识
·堆(二):维护堆的性质
·堆(三):建堆
·堆(四):优先队列
·排序算法:堆排序
·利用heapq模块实现堆


如下图,堆是一个数组,它可以被看成一个近似的完全二叉树,树上的每一个结点对应数组中的一个元素。除了最底层外,该树是完全充满的,而且是从左向右填充。表示堆的数组 A A A包括两个属性: A . l e n g t h A. length A.length给出数组元素的个数, A . h e a p − s i z e A.heap-size A.heapsize表示有多少个堆元素存储在该数组中。也就是说,虽然 A [ 1 ⋯ A . l e n g t h ] A[1\cdots A.length] A[1A.length]可能都存有数据,但只有 A [ 1 ⋯ A . h e a p − s i z e ] A[1\cdots A.heap-size] A[1A.heapsize]中存放的是堆的有效元素,这里, 0 ≤ A . h e a p − s i z e ≤ A . l e n g t h 0\leq A.heap-size\leq A.length 0A.heapsizeA.length。树的根结点是 A [ 1 ] A[1] A[1],这样给定一个结点的下标 i i i,我们很容易计算得到它的父结点、左孩子和右孩子的下标:

def parent(i):
    return int(i/2)
def left(i):
    return 2i 
def right(i):
    return 2i+1

堆
在大多数计算机上,通过将 i i i的值左移一位,left(i)过程可以在一条指令内计算出 2 i 2i 2i,采用类似方法,在right(i)过程中也可以通过将 i i i的值左移1位并在低位加1,快速计算得到 2 i + 1 2i+1 2i+1

至于parent(i)过程,则可以通过把 i i i的值右移1位计算得到 ⌊ i 2 ⌋ \lfloor\frac{i}{2}\rfloor 2i。在堆排序的好的实现中,这个函数通常是以“宏”或者“内联函数”的方式实现的二叉堆可以分为两种形式:最大堆和最小堆。

在这两种堆中,结点的值都要满足堆的性质,但一些细节定义则有所差异。在最大堆中,最大堆性质是指除了根以外的所有结点 i i i都要满足: A [ p a r e n t ( i ) ] ≥ A [ i ] A[parent(i)] \geq A[i] A[parent(i)]A[i]也就是说,某个结点的值至多与其父结点一样大。因此,堆中的最大元素存放在根结点中;并且,在任一子树中,该子树所包含的所有结点的值都不大于该子树根结点的值。

最小堆的组织方式正好相反:最小堆性质是指除了根以外的所有结点 i i i都有 A [ p a r e n t ( i ) ] ≤ A [ i ] A[parent(i)] \leq A[i] A[parent(i)]A[i]最小堆中的最小元素存放在根结点中。在堆排序算法中,我们使用的是最大堆。最小堆通常用于构造优先队列,在后面的文章中我们会再具体讨论。对于某个特定的应用来说,我们必须明确需要的是最大堆还是最小堆;而当某一属性既适合于最大堆也适合于最小堆的时候,我们就只使用“堆”这一名词。

如果把堆看成是一棵树,我们定义一个堆中的结点的高度就为该结点到叶结点最长简单路径上边的数目;进而我们可以把堆的高度定义为根结点的高度。既然一个包含 n n n个元素的队可以看做一棵完全二又树,那么该堆的高度是 O ( lg ⁡ n ) O(\lg n) O(lgn)。我们会发现,堆结构上的一些基本操作的运行时间至多与树的高度成正比,即时间复杂度为 O ( lg ⁡ n ) O(\lg n) O(lgn)。在后续的文章中,我们将介绍一些基本过程,并说明如何在排序算法和优先队列中应用它们。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

von Neumann

您的赞赏是我创作最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值