[数据结构].堆(优先队列)

堆(优先队列)

堆的定义

一种树形数据结构,分大根堆小根堆

大根堆(max heap)满足所有父节点不小于其任意子节点。

小根堆(min heap)满足所有父节点不大于其任意子节点。

在这里,我们只考虑二叉堆。二叉堆是一棵完全二叉树

堆的操作

  • 插入新元素(Ο(logN))
  • 查询最值(Ο(1))
  • 删除最大值(Ο(logN))
  • 修改元素(Ο(logN))

C++实现

STL实现

例题

1.合并果子

  • 有N堆果子,每次可以选择任意两堆合并,需要花费的代价是两堆果子的数量之和。
  • 可见,经过N-1次合并后,果子只剩下一堆。
  • 求将果子合并成一堆需要花费的最少代价。
  • 初始果子堆数不超过100000.
Solution

可见,每堆果子分别被合并了N-1次,N-2次,N-3次……1次
则数量越小的堆合并次数应越多。
创建一个小根堆,每次合并堆顶与其小儿子计入总数,相当于修改小儿子(Ο(logN)),堆顶删除(Ο(logN))。
复杂度(Ο(NlogN))


2.黑匣子

起先黑匣子为空。现在执行一系列命令,命令有两类:

  1. ADD(x):把元素x放入黑匣子;
  2. GET:输出黑匣子内第K大的数,其中K为当前执行GET操作的总次数。

命令条数不超过500000。

Solution

先考虑寻找第K大数,即寻找数列中第K大的数。
因为要输出第K大的数,故维护一个size是K的小根堆,堆顶即当前第K小的数。输入的数与堆顶元素比较,若比其大则堆顶变成当前第K+1大的数,故替换堆顶。

故此题利用两个堆,一个小根堆,一个大根堆,小根堆保存所有前K大的值,大根堆保存所有其它的值,即小根堆中的值严格大于等于大根堆中的值,大根堆堆顶为K+1大的数。每次输入元素放入大根堆中。K增加,则将原大根堆的根元素放入小根堆中。


3.两序列和的前n小元素

  • 给出两个长度为n的有序表(非降序表)A和B, 在A和B中各任取一个相加, 可以得到n^2个和。
  • 求这些和最小的n个。
  • n<=10^5.
Solution

先考虑k路归并问题

  • 把k个有序表合并成一个有序表.
  • 求前q个元素。

因为k个表都是有序的,故每个表第一个数据最小(以最小为例)。故比较每个表第一个数据,并输出最小值。可把每个表第一个数据建堆维护,输出最小后再在该值所在表中调取下个元素。

故此题可以把这些和看成n个有序表:

  • A[1]+B[1] <= A[1]+B[2] <= A[1]+B[3] <=…
  • A[2]+B[1] <= A[2]+B[2] <= A[2]+B[3] <=…
  • A[n]+B[1] <= A[n]+B[2] <= A[n]+B[3] <=…

4.n序列和的前n小元素

  • 上一题的加强版
  • 给出n个长度为n的有序表(非降序表)A1,A2,A3……An, 在其中各取一个相加, 可以得到n^n个和。
  • 求这些和最小的n个。
  • n<=750.
Solution

两两合并即可。


5.丑数

  • 对于一给定的素数集合S = {p1, p2, …, pK}, 来考虑那些质因数全部属于S 的数的集合。
  • 这个集合包括:p1, p1p2, p1p1, 和p1p2p3 (还有其它)。
  • 这是个对于一个输入的S的丑数集合。
  • 注意:我们不认为1是一个丑数。你的工作是对于输入的集合S去寻找集合中的第N个丑数。

6.轮廓线

  • 每一个建筑物用一个三元组表示(L, H, R), 表示
    左边界, 高度和右边界
  • 轮廓线用X, Y, X, Y…这样的交替式表示
  • 右图的轮廓线为: (1, 11, 3, 13, 9, 0, 12, 7, 16,
    3, 19, 18, 22, 3, 23, 13, 29, 0)
  • 给N个建筑,求轮廓线Eg.5

7.Hoax or what(UVa11136)


引用

http://blog.csdn.net/hishentan/article/details/39099923?utm_source=tuicool&utm_medium=referral

UNFINISHED

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值