配对堆gydF4y2Ba
配对堆gydF4y2Ba是具体的实现吗gydF4y2Ba堆gydF4y2Ba数据结构。他们已经快gydF4y2Ba摊销gydF4y2Ba操作的运行时间。成对堆是一种自我调整gydF4y2Ba二项堆gydF4y2Ba.当操作碰巧保持平衡时,自我调整结构会自行调整,例如,angydF4y2BaAVL树gydF4y2Ba这是自我调整或再平衡的例子吗gydF4y2Ba二叉搜索树gydF4y2Ba.gydF4y2Ba
尽管成对堆的实现非常简单,但它们可能很难分析。事实上,找到配对堆操作运行时间的确切界限仍然是一个悬而未决的问题gydF4y2Ba[1]gydF4y2Ba,但当前运行时间的最佳猜测列在复杂性部分。gydF4y2Ba
配对堆用于关联的算法gydF4y2Ba最小生成树gydF4y2Ba,并且像其他堆一样,可以使用配对堆来实现gydF4y2Ba优先级队列gydF4y2Ba.gydF4y2Ba
内容gydF4y2Ba
配对堆的结构gydF4y2Ba
配对堆可以是(gydF4y2Ba一个gydF4y2Ba)空堆或(gydF4y2BabgydF4y2Ba)根和配对堆列表(可能为空)。配对堆维护一个gydF4y2Ba最小堆属性gydF4y2Ba所有父节点的值总是小于其子节点的值(如果配对堆是Max堆,则维护Max -heap属性)。gydF4y2Ba
每个节点跟踪以下信息:指向最左边的子节点的指针和指向同级节点的指针。上面显示的配对堆中的指针是这样的。gydF4y2Ba
最小功能gydF4y2Ba
下面是对堆如何实现堆的基本功能以及每个操作的时间复杂度。这些操作描述了最小配对堆,但可以很容易地重新安排以适用于最大配对堆。gydF4y2Ba
找到最小gydF4y2Ba
在配对堆中,找到最小元素非常简单——只需要返回堆的顶部元素。gydF4y2Ba
下面是描述此操作的伪代码。gydF4y2Ba[2]gydF4y2Ba
1 2 3 4 5 5gydF4y2Ba |
|
合并gydF4y2Ba
如果合并发生在非空配对堆和空配对堆之间,gydF4y2Ba合并gydF4y2Ba
只返回非空的配对堆。如果两个配对堆都是非空的,则gydF4y2Ba合并gydF4y2Ba
函数返回一个新堆,其中两个堆的最小根是新组合堆的根,并将另一个堆添加到子堆列表中。gydF4y2Ba
下面是描述此操作的伪代码。gydF4y2Ba[2]gydF4y2Ba
1 2 3 4 5 6 7 8 9gydF4y2Ba |
|
提取最小gydF4y2Ba
在最小堆中,最小元素是堆的根。要删除该元素,请删除根节点。如果根有两个或更多的子树,这些子树必须合并成一个单独的树。因为没有父指针,所以很难判断删除是否会导致堆属性冲突(与其他堆实现不同)。有许多方法可以检查是否引起了堆冲突,但最简单的方法称为gydF4y2Ba双行程配对gydF4y2Ba或者一个gydF4y2Ba双行程合并gydF4y2Ba.第一次,双通道配对从左到右合并树对,第二次,从右到左合并最右边的子树和其余的子树,每次合并一棵树。双通道配对的灵感来自gydF4y2Ba倾斜的树木gydF4y2Ba.gydF4y2Ba
这些图像显示了双通道合并是如何工作的。gydF4y2Ba
下面是描述此操作的伪代码。gydF4y2Ba[2]gydF4y2Ba
12 3 4 5 6 7 8 9 10 11 12 13gydF4y2Ba |
|
插入gydF4y2Ba
插入元素就像将元素与堆合并一样。gydF4y2Ba
下面是一个添加的节点没有违反min-heap属性的示例。gydF4y2Ba
下面是一个插入的节点违反min-heap属性的例子(因为它小于根节点),并且必须成为根节点。gydF4y2Ba
下面是描述此操作的伪代码。gydF4y2Ba[2]gydF4y2Ba
1 2gydF4y2Ba |
|
删除gydF4y2Ba
删除节点gydF4y2Ba ,分离以节点为根的子树gydF4y2Ba .然后,删除gydF4y2Ba 从树中提取它的子树,并使用两步方法将其合并到一个子树中(如提取-min部分所述)。将分离的子树与由两次遍历产生的子树合并。gydF4y2Ba
假设我们想要删除根节点,gydF4y2Ba ,从这个配对堆。我们将从指针的角度来考虑堆。gydF4y2Ba[3]gydF4y2Ba
开始堆。gydF4y2Ba
当我们删除gydF4y2Ba ,gydF4y2Ba ,gydF4y2Ba ,gydF4y2Ba ,gydF4y2Ba ,gydF4y2Ba 不再是兄弟姐妹。所以移除指针gydF4y2Ba 来gydF4y2Ba ,然后删除之间的兄弟点gydF4y2Ba ,gydF4y2Ba ,gydF4y2Ba ,gydF4y2Ba ,gydF4y2Ba .gydF4y2Ba
通过发生。gydF4y2Ba
最后,它们合并在一起。gydF4y2Ba
降低关键gydF4y2Ba
减小节点的键值gydF4y2Ba ,如果gydF4y2Ba 已经是根还是如果gydF4y2Ba 大于或等于其父键的新键,则不需要其他步骤。如果gydF4y2Ba 是一个新键,并且小于其父键的值,为了维护min-heap属性,必须采取操作来生成有效的堆。gydF4y2Ba
在对堆时,纠正措施如下。gydF4y2Ba
删除根在的子树gydF4y2Ba
将得到的两棵树合并在一起gydF4y2Ba
实现gydF4y2Ba
下面是配对堆的伪代码实现。gydF4y2Ba[4]gydF4y2Ba
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23gydF4y2Ba |
|
Python对堆的实现可能很长,但这里有一些Python对堆的例子:gydF4y2Ba在这里gydF4y2Ba,gydF4y2Ba在这里gydF4y2Ba,gydF4y2Ba在这里gydF4y2Ba.gydF4y2Ba
结对堆的运行时间总结gydF4y2Ba
这是一张表格gydF4y2Ba[5]gydF4y2Ba描述了gydF4y2Ba摊销gydF4y2Ba对配对堆进行操作的运行时间。gydF4y2Ba
操作gydF4y2Ba | 实际运行时间gydF4y2Ba | 平摊运行时间gydF4y2Ba |
插入gydF4y2Ba | ||
删除gydF4y2Ba | ||
找到最小值gydF4y2Ba | ||
取出最小值gydF4y2Ba | ||
降低关键gydF4y2Ba | ||
合并gydF4y2Ba |
在实践中,配对堆比二进制堆和斐波那契堆快。gydF4y2Ba[2]gydF4y2Ba.许多研究表明,在实现中,配对堆的性能优于斐波那契堆gydF4y2Ba迪杰斯特拉算法gydF4y2Ba和拘谨的gydF4y2Ba最小生成树gydF4y2Ba算法。gydF4y2Ba[5]gydF4y2Ba
另请参阅gydF4y2Ba
参考文献gydF4y2Ba
- Fredman, M., Sedgewick, R., Sleator, D., and Tarjan, R.gydF4y2Ba配对堆:一种新的自调整堆形式gydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdfgydF4y2Ba
- , .gydF4y2Ba配对堆gydF4y2Ba.2016年6月7日,从gydF4y2Bahttps://en.wikipedia.org/wiki/Pairing_heapgydF4y2Ba
- 艾伦,S。gydF4y2Ba合并优先队列gydF4y2Ba.2016年7月3日,从gydF4y2Bahttp://digital.cs.usu.edu/~allan/DS/Notes/Ch23.pdfgydF4y2Ba
- Fredman, M。gydF4y2Ba二项式、斐波那契和配对堆gydF4y2Ba.2016年6月7日,从gydF4y2Bahttp://web.onda.com.br/abveiga/capitulo7-ingles.pdfgydF4y2Ba
- , .gydF4y2Ba优先级队列gydF4y2Ba.2016年6月7日,从gydF4y2Bahttp://www.uqac.ca/azinflou/Fichiers840/pairing.pdfgydF4y2Ba