二叉堆、并查集与树状数组.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
PAGE PAGE 1 二叉堆、并查集和树状数组 优先队列 ? 优先队列(priority queue): 可以把元素加入到优先队列中, 也可以从队列中取出优先级最高的元素, 即以下ADT – Insert(T, x): 把x加入优先队列中 – DeleteMin(T, x): 获取优先级最高的元素x, 并把它从优先队列中删除堆的操作 ? 用二叉堆(binary heap)很容易实现优先队列 ? 除了实现优先队列, 堆还有其他用途, 因此操作比优先队列多 – Getmin(T, x): 获得最小值 – Delete(T, x): 删除任意已知结点 – DecreaseKey(T, x, p): 把x的优先级降为p – Build(T, x): 把数组x建立成最小堆 堆的定义 ? 堆是一个完全二叉树 – 所有叶子在同一层或者两个连续层 – 最后一层的结点占据尽量左的位置 ? 堆性质 – 为空, 或者最小元素在根上 – 两棵子树也是堆 存储方式 ? 最小堆的元素保存在heap[1..hs]内 – 根在heap[1] – K的左儿子是2k, K的右儿子是2k+1, – K的父亲是[k/2] 删除最小值元素 ? 三步法 – 直接删除根 – 用最后一个元素代替根上元素 – 向下调整 ? 首先选取当前结点p的较大儿子. 如果比p大, 调整停止, 否则交换p和儿子, 继续调整 void sink(int p){ int q=p1, a = heap[p]; while(q=hs){ if(qhsheap[q+1]heap[q])q++; if(heap[q]=a) break; heap[p]=heap[q]; p=q; q=p1; } heap[p] = a; } 插入元素和向上调整 ? 插入元素是先添加到末尾, 再向上调整 ? 向上调整: 比较当前结点p和父亲, 如果父亲比p小,停止; 否则交换父亲和p, 继续调整 void swim(int p){ int q = p1, a = heap[p]; while(q aheap[q]){ heap[p]=heap[q]; p=q; q=p1; } heap[p] = a; } 堆的建立 ? 从下往上逐层向下调整. 所有的叶子无需调整,因此从hs/2开始. 可用数学归纳法证明循环变量为i时, 第i+1, i+2, …n均为最小堆的根 void insert(int a) { heap[++hs]=a; swim(hs); } int getmin() { int r=heap[1]; heap[1]=heap[hs--]; sink(1); return r; } int decreaseKey(int p, int a) { heap[p]=a; swim(p); } void build() { for(int i=hs/2;i0;i--) sink(i); } 时间复杂度分析 ? 向上调整/向下调整 – 每层是常数级别, 共logn层, 因此O(logn) ? 插入/删除 – 只调用一次向上或向下调整, 因此都是O(logn) ? 建堆 – 高度为h的结点有n/2h+1个,总时间为 例1. k路归并问题 ? 把k个有序表合并成一个有序表. ? 元素共有n个. 分析 ? 每个表的元素都是从左到右移入新表 ? 把每个表的当前元素放入二叉堆中, 每次删 除最小值并放入新表中, 然后加入此序列的下一个元素 ? 每次操作需要logk时间, 因此总共需要nlogk 的时间 例2. 序列和的前n小元素 ? 给出两个长度为n的有序表A和B, 在A和B中各任取一个, 可以得到n2个和. 求这些和最小的n个 分析 ? 可以把这些和看成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] =… ? 类似刚才的算法, 每次O(logn), 共取n次最小元素,共O(nlogn) 例3. 轮廓线 ? 每一个建筑物用一个三元组表示(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个建筑,求轮廓线 分析 ? 算法一: 用数组记录每一个元线段的高度 – 离散化, 有n个元线段 – 每次插入可能影响n个元线段, O(n), 共O(n2) – 从左到右扫描元线段高度, 得轮廓线 ? 算法二:每个建筑的左右边界为事件

文档评论(0)

jyf123 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

版权声明书
用户编号:6153235235000003

1亿VIP精品文档

相关文档