Jac*_*ale 3 algorithm data-structures pairing-heap
我正在阅读配对堆.
这很简单,唯一棘手的部分是delete_min操作.
唯一不重要的基本操作是从堆中删除最小元素.标准策略首先从左到右合并子堆(这是赋予此数据结构名称的步骤),然后从右到左合并生成的堆列表:
我不认为我需要在这里复制/粘贴代码,因为它在wiki链接中.
我的问题是
为什么他们这两个合并?
为什么他们首先合并?没有直接合并他们所有?
合并后,为什么从右到左专门合并?
Jim*_*hel 10
对于配对堆,向堆中添加项是O(1)操作,因为它只是将节点添加为新根(如果它小于当前根),或者作为当前根的第一个子节点.因此,如果您创建了一个配对堆并将数字0到9添加到它中,那么您将最终得到:
0
|
-----------------
| | | | | | | | |
9 8 7 6 5 4 3 2 1
Run Code Online (Sandbox Code Playgroud)
如果然后执行delete-min,则必须查看每个子项以确定最小项并构建新堆.如果你使用天真的从左到右组合方法,你最终得到这个树:
1
|
---------------
| | | | | | | |
9 8 7 6 5 4 3 2
Run Code Online (Sandbox Code Playgroud)
下次你执行delete-min时,你必须查看其余8个孩子等.使用这种技术,创建然后从堆中删除所有项目将是一个O(n ^ 2)操作.
成对组合然后组合这对的双程方法产生更有效的结构.考虑第一种情况.删除最小项目后,我们留下了九个孩子.它们从左到右成对组合产生:
8 6 4 2 1
/ / / /
9 7 5 3
Run Code Online (Sandbox Code Playgroud)
然后我们将这些对从右到左组合起来.步骤:
8 6 4 1
/ / / /
9 7 5 2
/
3
8 6 1
/ / / \
9 7 2 4
/ /
3 5
8 1
/ |
9 ---------
6 4 2
/ / /
7 5 3
1
|
----------
8 6 4 2
/ / / /
9 7 5 3
Run Code Online (Sandbox Code Playgroud)
现在,下次我们调用delete-min时,只有四个节点需要检查,下一次之后只会有两个节点.使用两遍组合方法将子级别的节点数量减少至少一半.我展示的安排是最糟糕的情况.如果项目按升序排列,则第一个delete-min操作将导致树在根目录下只有两个子节点.
这是配对堆的摊销复杂性的一个特别好的例子.insert是O(1),但是一堆插入操作后的第一个delete-min是O(n),其中是自上次delete-min以来插入的项目数.双通组合规则的优点在于它可以快速重组堆以降低O(n)复杂度.n
使用此组合规则,delete-min的分摊复杂度为O(log n).使用严格的从左到右的规则,它是O(n).