转自http://dsqiu.iteye.com/blog/1714961
斐波那契堆主要有两个缺点:编程实现难度较大和实际效率没有理论的那么快(由于它的存储结构和四个指针)。Pairing Heap的提出就是弥补斐波那契堆的两个缺点——编程简单操作的时间复杂度和斐波那契堆一样。
Pairing Heap其实就是一个具有堆(最大堆或最小堆)性质的树,它的特性不是由它的结构决定的,而是由于它的操作(插入,合并,减小一个关键字等)决定的。
注意:图解过程是以最大堆来演示的,但是代码是以最小堆来写的,见谅!
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); }
#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.csdn.net/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: 算法导论和维基百科