配对堆gydF4y2Ba
配对堆gydF4y2Ba是否有具体的实现gydF4y2Ba堆gydF4y2Ba数据结构。他们吃得很快gydF4y2Ba摊销gydF4y2Ba它们操作的运行时间。配对堆是一种自我调整的类型gydF4y2Ba二项堆gydF4y2Ba.当业务恰好保持平衡时,自我调整结构会自我调整gydF4y2BaAVL树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 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
下面是一个示例,其中添加的节点不违反最小堆属性。gydF4y2Ba
下面的例子中,插入的节点违反了最小堆属性(因为它小于根节点),必须成为根节点。gydF4y2Ba
下面是描述该操作的伪代码。gydF4y2Ba[2]gydF4y2Ba
1 2gydF4y2Ba |
|
删除gydF4y2Ba
删除节点gydF4y2Ba ,分离以节点为根的子树gydF4y2Ba .然后,删除gydF4y2Ba 并使用两步方法将其子树合并为一个子树(如extract-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 已经是根还是ifgydF4y2Ba 是大于或等于其父键的新键,不需要其他步骤。如果gydF4y2Ba 是一个新键,并且小于它的父键的值,要维护最小堆属性,必须采取操作来生成有效的堆。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
- 弗雷德曼,M.,塞奇威克,R.,斯莱托,D.和塔尔扬,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
- 弗雷德曼,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