转自http://dsqiu.iteye.com/blog/1714961
1.Pairing Heap简介
斐波那契堆主要有两个缺点:编程实现难度较大和实际效率没有理论的那么快(由于它的存储结构和四个指针)。Pairing Heap的提出就是弥补斐波那契堆的两个缺点——编程简单操作的时间复杂度和斐波那契堆一样。
Pairing Heap其实就是一个具有堆(最大堆或最小堆)性质的树,它的特性不是由它的结构决定的,而是由于它的操作(插入,合并,减小一个关键字等)决定的。
1.1Pairing Heap的ADT
2.Pairing Heap 的操作
注意:图解过程是以最大堆来演示的,但是代码是以最小堆来写的,见谅!
2.1.合并两个子堆
2.2. 插入一个结点
2.3.增加(减小)一个关键字
- PairHeap* PairHeap_DecreaseKey(PairHeap *p, PairHeap *pos, int d)
- {
- if(d < 0)
- return p;
- pos->key = pos->key - d;
- if(p == pos)
- return p;
- if(pos->sibling != NULL)
- pos->sibling->prev = pos->prev;
- if(pos->prev->child = pos)
- pos->prev->child = pos->sibling;
- else
- pos->prev->sibling = p->sibling;
- p->sibling = NULL;
- return merge_subheaps(p, pos);
- }
2.5.删除最小结点
3.Pairing Heap完整代码实现
- #include <stdlib.h>
- typedef struct PairingHeapNode
- {
- int key;
- struct PairingHeapNode* child;
- struct PairingHeapNode* sibling;
- struct PairingHeapNode* prev;
- }PairHeap;
- static PairHeap* merge_subheaps(PairHeap *p, PairHeap *q);
- static PairHeap* combine_siblings(PairHeap *p);
- PairHeap* PairHeap_insert(PairHeap *p, int key)
- {
- PairHeap *node;
- node = (PairHeap*)malloc(sizeof(*node));
- if(node == NULL)
- return NULL;
- node->key = key;
- node->child = node->sibling = node->prev = NULL;
- if(p == NULL)
- return node;
- else
- return merge_subheaps(p, node);
- }
- PairHeap* PairHeap_DecreaseKey(PairHeap *p, PairHeap *pos, int d)
- {
- if(d < 0)
- return p;
- pos->key = pos->key - d;
- if(p == pos)
- return p;
- if(pos->sibling != NULL)
- pos->sibling->prev = pos->prev;
- if(pos->prev->child = pos)
- pos->prev->child = pos->sibling;
- else
- pos->prev->sibling = p->sibling;
- p->sibling = NULL;
- return merge_subheaps(p, pos);
- }
- PairHeap* PairHeap_DeleteMin(int *key, PairHeap *p)
- {
- PairHeap *new_root;
- if(p == NULL)
- return NULL;
- else
- {
- *key = p->key;
- if(p->child != NULL)
- new_root = combine_siblings(p->child);
- free(p);
- }
- return new_root;
- }
- static PairHeap* combine_siblings(PairHeap *p)
- {
- PairHeap *tree_array[1024];
- int i, count;
- if(p->sibling == NULL)
- return p;
- for(count = 0; p != NULL; count++)
- {
- tree_array[count] = p;
- p->prev->sibling = NULL;
- p = p->sibling;
- }
- tree_array[count] = NULL;
- for(i = 1; i < count; i++)
- tree_array[i] = merge_subheaps(tree_array[i-1], tree_array[i]);
- return tree_array[count-1];
- }
- static PairHeap* merge_subheaps(PairHeap *p, PairHeap *q)
- {
- if(q == NULL)
- return p;
- else if(p->key <= q->key)
- {
- q->prev = p;
- p->sibling = q->sibling;
- if(p->sibling != NULL)
- p->sibling->prev = p;
- q->sibling = p->child;
- if(q->sibling != NULL)
- q->sibling->prev = q;
- p->child = q;
- return p;
- }
- else
- {
- q->prev = p->prev;
- p->prev = q;
- p->sibling = q->child;
- if(p->sibling != NULL)
- p->sibling->prev = p;
- q->child = p;
- return q;
- }
- }
小结
终于到小结了,这篇文章写得比较吃力,如斐波那契堆的“减小一个关键字”的操作我就对使用级联剪切还没有找到解释,还有还没有找到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_Shadow:http://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 demonstration:http://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: 算法导论和维基百科