结构之美——优先队列三大结构(三)——Pairing Heap

本文详细介绍了一种简单且高效的自调整堆——Pairing Heap(配对堆),并提供了完整的C语言实现代码。Pairing Heap旨在解决斐波那契堆在实际应用中遇到的问题,通过简单的合并操作实现了与斐波那契堆相同的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自http://dsqiu.iteye.com/blog/1714961

1.Pairing Heap简介

斐波那契堆主要有两个缺点:编程实现难度较大和实际效率没有理论的那么快(由于它的存储结构和四个指针)。Pairing Heap的提出就是弥补斐波那契堆的两个缺点——编程简单操作的时间复杂度和斐波那契堆一样。

Pairing Heap其实就是一个具有堆(最大堆或最小堆)性质的树,它的特性不是由它的结构决定的,而是由于它的操作(插入,合并,减小一个关键字等)决定的。

 

1.1Pairing Heap的ADT

 

C代码
  1. PairingHeapNode  
  2. {  
  3.     int                         key;  
  4.     struct  PairingHeapNode*    child;  
  5.     struct  PairingHeapNode*    sibling;  
  6.     struct  PairingHeapNode*    prev;  
  7.   
  8. }PairHeap;  

 

2.Pairing Heap 的操作

注意:图解过程是以最大堆来演示的,但是代码是以最小堆来写的,见谅!

2.1.合并两个子堆


C代码
  1. static PairHeap* merge_subheaps(PairHeap *p, PairHeap *q)  
  2. {  
  3.     if(q == NULL)  
  4.         return p;  
  5.     else if(p->key <= q->key)  
  6.     {  
  7.         q->prev = p;  
  8.         p->sibling = q->sibling;  
  9.         if(p->sibling != NULL)  
  10.             p->sibling->prev = p;  
  11.   
  12.         q->sibling = p->child;  
  13.         if(q->sibling != NULL)  
  14.             q->sibling->prev = q;  
  15.   
  16.         p->child = q;  
  17.         return p;  
  18.     }  
  19.     else  
  20.     {  
  21.         q->prev = p->prev;  
  22.         p->prev = q;  
  23.         p->sibling = q->child;  
  24.         if(p->sibling != NULL)  
  25.             p->sibling->prev = p;  
  26.   
  27.         q->child = p;  
  28.         return q;  
  29.     }  
  30. }  
 

 

2.2. 插入一个结点


C代码
  1. PairHeap* PairHeap_insert(PairHeap *p, int key)  
  2. {  
  3.     PairHeap *node;  
  4.   
  5.     node = (PairHeap*)malloc(sizeof(*node));  
  6.     if(node == NULL)  
  7.         return NULL;  
  8.   
  9.     node->key = key;  
  10.     node->child = node->sibling = node->prev = NULL;  
  11.   
  12.     if(p == NULL)  
  13.         return node;  
  14.     else  
  15.         return merge_subheaps(p, node);  
  16. }  

2.3.增加(减小)一个关键字


 


C代码  
  1. PairHeap* PairHeap_DecreaseKey(PairHeap *p, PairHeap *pos, int d)  
  2. {  
  3.     if(d < 0)  
  4.         return p;  
  5.   
  6.     pos->key = pos->key - d;  
  7.     if(p == pos)  
  8.         return p;  
  9.   
  10.     if(pos->sibling != NULL)  
  11.         pos->sibling->prev = pos->prev;  
  12.   
  13.     if(pos->prev->child = pos)  
  14.         pos->prev->child = pos->sibling;  
  15.     else  
  16.         pos->prev->sibling = p->sibling;  
  17.   
  18.     p->sibling = NULL;  
  19.     return merge_subheaps(p, pos);  
  20. }   

2.5.删除最小结点


 

 

3.Pairing Heap完整代码实现

 

C代码
  1. #include <stdlib.h>  
  2.   
  3. typedef struct PairingHeapNode  
  4. {  
  5.     int                         key;  
  6.     struct  PairingHeapNode*    child;  
  7.     struct  PairingHeapNode*    sibling;  
  8.     struct  PairingHeapNode*    prev;  
  9.   
  10. }PairHeap;  
  11.   
  12. static PairHeap* merge_subheaps(PairHeap *p, PairHeap *q);  
  13. static PairHeap* combine_siblings(PairHeap *p);  
  14.   
  15. PairHeap* PairHeap_insert(PairHeap *p, int key)  
  16. {  
  17.     PairHeap *node;  
  18.   
  19.     node = (PairHeap*)malloc(sizeof(*node));  
  20.     if(node == NULL)  
  21.         return NULL;  
  22.   
  23.     node->key = key;  
  24.     node->child = node->sibling = node->prev = NULL;  
  25.   
  26.     if(p == NULL)  
  27.         return node;  
  28.     else  
  29.         return merge_subheaps(p, node);  
  30. }  
  31.   
  32. PairHeap* PairHeap_DecreaseKey(PairHeap *p, PairHeap *pos, int d)  
  33. {  
  34.     if(d < 0)  
  35.         return p;  
  36.   
  37.     pos->key = pos->key - d;  
  38.     if(p == pos)  
  39.         return p;  
  40.   
  41.     if(pos->sibling != NULL)  
  42.         pos->sibling->prev = pos->prev;  
  43.   
  44.     if(pos->prev->child = pos)  
  45.         pos->prev->child = pos->sibling;  
  46.     else  
  47.         pos->prev->sibling = p->sibling;  
  48.   
  49.     p->sibling = NULL;  
  50.     return merge_subheaps(p, pos);  
  51. }  
  52.   
  53. PairHeap* PairHeap_DeleteMin(int *key, PairHeap *p)  
  54. {  
  55.     PairHeap *new_root;  
  56.   
  57.     if(p == NULL)  
  58.         return NULL;  
  59.     else  
  60.     {  
  61.         *key = p->key;  
  62.         if(p->child != NULL)  
  63.             new_root = combine_siblings(p->child);  
  64.   
  65.         free(p);  
  66.     }  
  67.     return new_root;  
  68. }  
  69.   
  70. static PairHeap* combine_siblings(PairHeap *p)  
  71. {  
  72.     PairHeap *tree_array[1024];  
  73.     int i, count;  
  74.   
  75.     if(p->sibling == NULL)  
  76.         return p;  
  77.   
  78.     for(count = 0; p != NULL; count++)  
  79.     {  
  80.         tree_array[count] = p;  
  81.         p->prev->sibling = NULL;  
  82.         p = p->sibling;  
  83.     }  
  84.     tree_array[count] = NULL;  
  85.   
  86.     for(i = 1; i < count; i++)  
  87.         tree_array[i] = merge_subheaps(tree_array[i-1], tree_array[i]);  
  88.   
  89.     return tree_array[count-1];  
  90. }  
  91.   
  92. static PairHeap* merge_subheaps(PairHeap *p, PairHeap *q)  
  93. {  
  94.     if(q == NULL)  
  95.         return p;  
  96.     else if(p->key <= q->key)  
  97.     {  
  98.         q->prev = p;  
  99.         p->sibling = q->sibling;  
  100.         if(p->sibling != NULL)  
  101.             p->sibling->prev = p;  
  102.   
  103.         q->sibling = p->child;  
  104.         if(q->sibling != NULL)  
  105.             q->sibling->prev = q;  
  106.   
  107.         p->child = q;  
  108.         return p;  
  109.     }  
  110.     else  
  111.     {  
  112.         q->prev = p->prev;  
  113.         p->prev = q;  
  114.         p->sibling = q->child;  
  115.         if(p->sibling != NULL)  
  116.             p->sibling->prev = p;  
  117.   
  118.         q->child = p;  
  119.         return q;  
  120.     }  
  121. }  
 

 

小结

终于到小结了,这篇文章写得比较吃力,如斐波那契堆的“减小一个关键字”的操作我就对使用级联剪切还没有找到解释,还有还没有找到Pairing Heap的定义,唯独只有自己理解和揣测(比如pairing heap没有明确的定义,本人个人理解pairing heap的独特性一定在他的操作,即行为决定特征)但总归还是相对完整,希望能对你有说帮助。如果你有任何建议、批评或补充,还请你不吝提出,不甚感激。更多参考请移步互联网。

 

 

 

 

参考:

酷~行天下: http://mindlee.net/2011/09/26/binomial-heaps/

Björn B. Brandenburg:http://www.cs.unc.edu/~bbb/#binomial_heaps

酷~行天下  http://mindlee.net/2011/09/29/fibonacci-heaps/

Adoo's blog http://www.roading.org/algorithm/introductiontoalgorithm/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E5%A0%86fibonacci-heaps.html

Golden_Shadowhttp://blog.youkuaiyun.com/golden_shadow/article/details/6216921

Sartaj Sahni:http://www.cise.ufl.edu/~sahni/dsaaj/enrich/c13/pairing.htm

⑦C++ template Fibonacci heap, with demonstrationhttp://ideone.com/9jYnv

"The pairing heap: a new form of self-adjusting heap"http://www.cs.cmu.edu/afs/cs.cmu.edu/user/sleator/www/papers/pairing-heaps.pdf

Vikas Tandi :http://programmingpraxis.com/2009/08/14/pairing-heaps/

http://www.cise.ufl.edu/~sahni/cop5536/slides/lec156.pdf

⑩+1: 算法导论和维基百科

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值