数据结构与算法学习笔记(十二)——堆

1、堆是一个完全二叉树,堆中的每一个节点的值都必须大于等于(小于等于)其子树中每个节点的值。
2、每个节点的值都大于等于其子树中的每个节点的值,此为大顶堆。大顶堆的堆顶元素为最大的元素
3、每个节点的值都小于等于其子树中的每个节点的值,此为小顶堆。小顶堆的堆顶元素为最小元素
在这里插入图片描述
上图中的1、2均为大顶堆,3为小顶堆,4不是堆

查找、插入、删除

1、查找:堆是完全二叉树,因此堆的存储方式也是数组存储。因此只要知道一个节点就可以推出其他节点的存储位置。
2、插入:若直接往叶子节点中插入一个元素会使堆不满足堆的特性,因此需要不断的堆化来调整。
(1)堆化分为从上往下堆化和从下往上堆化。
从上往下堆化:顺着节点路径从上往下对比,交换
从下往上堆化:顺着节点路径从下往上对比,交换
(2)在大顶堆中插入一个数据,直接插入在最后的叶子节点中,然后再从下往上进行堆化,直至满足堆的特性

插入节点为22
在这里插入图片描述
3、删除
(1)删除的元素一般是堆顶元素
(2)将要删除的堆顶元素p与最后的叶子节点q进行交换,p就被交换到了叶子节点处,删除p,再堆化,这样不会造成数据空洞。若直接删除堆顶元素,堆化完成后可能会出现数据空洞。
在这里插入图片描述
4、时间复杂度
因插入、删除的操作都是顺着节点路径进行比较、交换,因此操作次数和树的高度成正比,而堆是完全二叉树,完全二叉树的高度小于等于log2n,因此堆的插入和删除时间复杂度都为O(logn)

堆排序

堆排序分为两步,第一步建堆,第二步排序。大顶堆为例
1、建堆,两种方法
(1)类似插入操作,假设初始堆只有一个元素,将剩下的元素不断地插入堆中即可。
(2)将要建堆的数据先构建出一个完全二叉树,然后从最后一个非叶子节点开始从上往下的进行堆化。从上往下进行堆化,叶子节点无子节点,因此叶子节点无需进行比较。
在这里插入图片描述
在这里插入图片描述
建堆的时间复杂度为O(n)
2、排序
(1)从堆中取出堆顶元素,放在数组下标为n的位置。即从大顶堆中删除堆顶元素,放在数组最后
(2)将剩下的n-1个元素进行堆化
(3)堆化完成后,再将堆顶元素放在数组下标为n-1的位置
(4)循环至堆中只有最后一个元素,排序完成
时间复杂度为O(nlogn)
3、堆排序与快速排序比较
(1)堆是跳着访问数据,快排则是顺序访问数据
(2)堆排需要先建堆,建堆会打乱数据的原始顺序,且堆排的交换次数多于快排

堆的应用

1、优先级队列
将优先级高的元素放在堆顶,每次直接从堆顶取元素即可
2、求TOP K
将n个元素取出k个建小顶堆,再从n-k个元素中逐一取出元素,比较堆顶元素,若比堆顶元素小则不处理;比堆顶元素大则插入堆中,并删除堆顶元素
3、求中位数(n个数据已从小到大排序)
(1)大顶堆存储前半部分的数据,小顶堆存储后半部分的元素,大顶堆的堆顶元素即为中位数
(2)大小顶堆中的个数需满足:n为偶数,两个堆的数据都是n/2;n为奇数,大顶堆的数据个数为n/2+1,小顶堆的数据个数为n/2
(3)若有新数据p,若p比小顶堆的堆顶元素大,则插入小顶堆中;若p比小顶堆的堆顶元素小,则插入大顶堆中。若插入p后,大小顶堆的数据个数不满足要求,则需要堆个数进行调整,直至满足要求
4、求95%的数,操作与求中位数类似,只是大小顶堆的个数不是对半分,而是大顶堆为95%的数据,小顶堆为5%的数据

图源:王争——数据结构与算法之美

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值