算法设计搬运(3)——Heaps

前言

570 Lecture 3 的内容。 Lecture 3 的前半段相当于 review,所讲 binary heap 内容基本被都数据结构覆盖,基础的可能会简略一点。后半段讨论了 Binomial Heap 和 Fibonacci Heap。

3. Heaps

3.1 Binary Heap

二叉堆(最小堆):complete binary tree that satisfies the heap odering.
也就是首先它是个完全二叉树,其次满足堆的性质,(没有声明默认最小)即左右子树都小于等于根元素。堆顶元素最小,或者理解为优先级最高。
实现是用 array,array[1...n],对于 i-th 元素,左孩子2i,右孩子2i+1,一般提供几种操作 insert,deleteMin,heapify和changeKey。

  • Insert. 插入元素放在 array 里 n+1 的位置,依次与 parent比较,如果小就交换,直到根节点。因为是完全二叉树,所以 worst-case 比较次数O(log n),swap O(1),因此复杂度 O(log n)。

    insert

  • DeleteMin. 把堆顶元素和最后一个元素交换,堆(array)的长度 -1,从新的根节点开始,如果其比左右孩子中任意一个小,那么就与左右孩子中更小的交换,直至不需要交换。worst case 也是从根节点一直交换到叶子节点,O(log n)。

    deleteMin

  • Heapify. 一般用来 offline 建堆。从前array的 n/2 处开始从底向上,对于每一个元素判断是否需要与左右孩子交换。不同于通过 insertion 建堆,Heapify O(n).

例:对 4,7,3,6,8,5,2,1 建堆,n insertion O(nlogn):


Build Heap

而 Heapify,从 n/ 2 处开始所有元素都只可能往叶子节点交换。根节点最坏情况交换 h 次,其2个子节点最多交换 h-1 次 ... 2h-1 在倒数第二层,交换一次。对于 worst case,total swap = 1·h +2·(h-1)+...+2^{h-1}·1 = \sum_{i=1}^{h}2^{h-i}·i = O(2^h),因为 h = \lfloor \log n\rfloor,heapify 整体复杂度 O(n).

Heapify

  • changeKey. 一般是优先队列的 op,修改一个节点的key。实现:如果 key 变小,那么就往上去比较交换,直到 root。如果变大,那么往叶子方向跟孩子比较交换(更小者),O(logn)。

Discussion Problem 1. 对于存储元素1,2,...,15 的堆最小的叶子节点可能是______。

Solution. 4. 如图。

example

还有一些其他数据结构的内容比如堆排序、top K 问题,以及归并 k 个有序数组。

解决 top K 有两种思路(给定unsorted array)。一种是直接建一个长度为 n 的最大堆,然后 deleteMax k 次。O(n) 建堆,deleteMax k 次 O(klogn),整体 O(n+klogn).
另一种思路则维护一个长度为 k 的堆,deleteMin 和 insert n-k 次,这样O(k) 建堆,维护需要 O(nlogk),整体复杂度O(nlogk).

这里的 top K 问题可能会涉及到 offline 和 online 的场景,也就是说我们能不能一次性获取到所有数据——是给定array,还是要一个一个数的等。思路二的好处是可以应对 online 场景,O(klogk) 建堆,n-k次 deletesMin 和 insert O(nlogk),整体 O(nlogk)。而如果要用思路一必须得一个一个 insert 的s建堆,那么整体复杂度 O(nlogn) 就很不理想了。而 offline 二者就其实差不多,所以算法很多时候还是得结合场景。

3.2 Binomial Heaps

回想上一篇的 amortized tree,二者相似。这里二项堆也是为了得到更好的 amortized cost。
首先是二项树,B0 是一个单一节点,Bn 是由两个 Bn-1合并而来。如图。

Binomial Tree

而 Binomial Heaps 就是 一个结构同 Binomial Tree 的链表,每一个树的秩都是唯一的,且每一棵树都具备堆的性质。每一个节点都包含了它的数值和它的秩,parent,child 和 sibling.

Binomial Heaps

那么就像 Binary counter一样,二项堆可以容纳任意个数,存放 n 个数的二项堆最多有 logn 个 堆。插入操作相当于是一次 increment。每一次插入,都是再链表里加入 B0,因此可能需要进行合并。最差情况下是所有的 bits 都要 flip,O(logn) 次合并(merge 先比较大小,然后指针 cost O(1) ),所以 worst-case 插入O(logn)。而对于 n 次插入而言,Binary Counter n 次 incremet,cost to flip each bit 都是 1,所以 amortized cost per operation = O(1). 如果用 accounting method 来分析的话那就是 O(2),1个 insert消耗掉,另一个用来给后续可能的 merge存着。

:insert 4, 7, 3, 2, 8, 3, 5, 6, 9 to an empty (eager) binomial heap.

insert (1)
insert (2)

而 deleteMin 首先要 findMin, O(logn) 因为 logn 个堆。而后需要删一个根元素就必然会 split 一个堆,worst-case 同样是所有 bits 都要 flip,100\implies011。所以 O(logn)。Delete的复杂度取决于最小值所在的位置,假设它是 Bi+1的 root,那么这次deleteMin 可能会有 i 次合并——i 个 filpped bits。尽管我们不能确定每一次最小元素所在位置——每一次的复杂度,但是对于 n 次 deleteMin,对应 B0 merge n-1次,B1 merge n-2次,B2 merge n-4次... total work = O(nlogn). Amortized cost per operation 仍然是 O(logn),并没有比binary heap 有提升。

deleteMin

在这里做一个 Binomial 和 Binary heap 建堆的比较。

Binary heap 建堆 分为 online 和 offline。worst-case 前者 n 次 insert,\Theta(nlogn);后者 heapify \Theta(n)。而 Binomial heap 建堆的amortized 复杂度\Theta(n)

(这是对于 eager binomial heap的情况,也就是每一次插入都要去维护数据结构)

与之对应的是 lazy binomial heap,插入的时候我们就只是把节点放在双向链表里,其他什么都不管,O(1)。维护的事情全部交给 deleteMin 来做。提升 insert性能 ,O(logn) \implies O(1)(worst-case),同时保持 deleteMin O(logn) 的 amortized cost。

lazy binomial heap 在插入时不再保持每一个 heap order 的 rank 唯一的性质。在 deleteMin 时,做两件事 一个是在森林里找到最小根,split 那个binomial heap,二是合并所有 oder 不唯一的,直到形成标准的 binomial heaps,order 唯一。这样来看最差情况其实是 O(n)。毕竟我们无法使 insert 和 deleteMin 都有 常数的 amortized cost,回想 Lecture 1 介绍的定理,“no comparison-based...”

3.3 Fibonacci Heaps

Lazy Binomial heaps 的扩展。对于 heaps collection的维护还是只交给 deleteMin,Fibonacci heaps 支持复杂度更低的 decreaseKey. 前面 lazy insert已经不再保持 binomial heap order 的唯一性,Fibonacci heaps 在此基础上不再要求链表里的节点都是标准的 binomial heap。

decreaseKey 不需要再维护 二项堆的结构,我们就直接把需要 decreasekey 的 node 直接 cut 掉,然后再加入到 collection 里面。这样就有了 O(1) 的复杂度。deleteMin的维护则要变得更复杂,这里还有很多问题但是 Victor 压根没讲。在理想情况下,amortized 复杂度O(logn)。

小节

这部分后面的内容 Victor 课上几乎都没讲明白,甚至连 为什么要引入 Binomial Heap和 Fibonacci Heap 的 motivation 都没讲。Lazy Binomial Heap 中 deleteMin 的实现和 amortized analysis,以及 Fibonacci Heap 的 实现和相应问题, decreaseKey 造成 森林里面 每一个 heap 的 shape 不再 well-constrained,对于 n 个 nodes,我们最多跟能会有 n^{\frac{1}{2}} 个 tree,相比之前 最多 logn 个 heap,最后再去维护就不能再保证deleteMin O(logn) 的 amortized 复杂度。

结果就是这部分内容,就这样不了了之了,考试的时候也没有考。Victor 天天吹自己编的教材,“我编的教材里所有内容浓缩了所有面试时可能会遇到的问题,认真看了,包你们找到工作...” 这部分课上没讲,算法设计上其实也没有... 但我还是会单独拿出来补充吧。毕竟 stanford cs 166 花了 两个 lecture,700 页的 slides 讲了这两个数据结构...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271