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

1.Pairing Heap简介

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

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

1.1Pairing Heap的ADT

C代码

PairingHeapNode
{
int                         key;
struct  PairingHeapNode*    child;
struct  PairingHeapNode*    sibling;
struct  PairingHeapNode*    prev;
}PairHeap;

2.Pairing Heap 的操作

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

2.1.合并两个子堆

C代码

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;
}
}

2.2. 插入一个结点

C代码

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);
}

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

C代码 
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完整代码实现

C代码
#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: 算法导论和维基百科

结构之美——优先队列三大结构(三)——Pairing Heap相关推荐

  1. 结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆

    实现优先队列结构主要是通过堆完成,主要有:二叉堆.d堆.左式堆.斜堆.二项堆.斐波那契堆.pairing 堆等. 1. 二叉堆 1.1. 定义 完全二叉树,根最小. 存储时使用层序. 1.2. 操作 ...

  2. Jemalloc 深入分析 之 配对堆Pairing Heap

    为了更好的阅读效果,推荐下载pdf文档: 详细文章请参考:<jemalloc 深入分析> https://github.com/everschen/tools/blob/master/DO ...

  3. 史上最强Js流程控制三大结构

    大家好!我是萧寒,今天给大家分享的是流程控制的三大语句. 文章目录 初识JavaScript(四) 流程控制语句 顺序结构 分支结构 if语句 if的加强版if else语句(双分支语句) if 语句 ...

  4. 麦肯锡著名的三大结构化工具:金字塔原理、MECE和逻辑树

    今天给大家重点介绍一下,麦肯锡著名的三大结构化工具:金字塔原理.MECE原理和逻辑树: 关于金字塔原理 对于金字塔原理这种逻辑思考工具,要想掌握,是需要花时间进行反复练习的,包括在培训的现场,是需要进 ...

  5. Linux 物理内存管理涉及的三大结构体之struct zone

    从Linux 物理内存管理涉及的三大结构体之struct page 中,大概知道了UMA和NUMA概念,同时也知道在每个node对应的内存范围内,都会将其分成不同的内存管理区域zone.之所以分成几类 ...

  6. 【濡白的C语言】初学者-从零开始-3(三大结构—顺序结构,分支结构,循环结构)

    前言 学习C语言,必须要掌握的是三大结构--顺序.分支和循环.一切C语言程序都可以用这三个结构总结,因此熟练掌握它们,对于写程序以及理解程序都是非常有必要的. 目录 顺序结构 变量声明 函数声明 循环 ...

  7. 详细介绍C语言三大结构(顺序结构,分支结构,循环结构)

    目录 1.  顺序结构 1.1介绍顺序结构 2.  分支结构 2.1  分支结构的介绍与实现逻辑 2.2  if 语句实现分支 2.3  switch  case语句 2.4两者的区别 3.   循环 ...

  8. Java的三大结构理解

    从结构化程序设计角度出发,java有三种结构:顺序.选择.循环. 一.顺序结构: JAVA的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行顺序结构是最简单的算法结构,语句与语句之间,框 ...

  9. Java 结构体之 JavaStruct 使用教程三 JavaStruct 数组进阶

    经过前面两篇博客的介绍,相信对于 JavaStruct 的认识以及编程使用,读者已经有一定的基础了.只要理解和实践结合起来,掌握还是很容易的.下面进行一些数组使用方面的实例说明及演示. 在结构体类中使 ...

最新文章

  1. python中值滤波去除反光_Python 实现中值滤波、均值滤波的方法
  2. 方舟修改显示服务器个数,方舟生存进化服务器模式设置教程
  3. noa格式转java_用IDEA查看反编译 - osc_1loi8uc4的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. OkHttp实现登录注册验证
  5. 祝福!微软 46 周年生日快乐!
  6. linux下延时1ms用什么函数,Linux下1ms分辨率定时器推荐方式
  7. 钉钉在线求饶?五星分期付款?爬取钉钉App Store真实评价数据并分析
  8. CUDA中的复数定义、开内存空间以及运算
  9. Python库:time库
  10. [NLP]OpenNLP标记器的使用
  11. Linux:管线命令
  12. “流量注入”***模式的探讨
  13. 编写二分查找和使用集合类的二分查找实现
  14. [论文写作-词汇] 这么多特别,该用哪个?special especial specific particular peculiar exceptional extraordinary
  15. 几何分布(一种离散分布)
  16. python中字典的索引_python字典索引
  17. 《很杂很杂的杂学知识》 学习笔记
  18. BeagleBone Black– 智能家居控制系统 LAS - ESP8266 UDP 服务
  19. 06-Python类和对象
  20. 重新认识java(五) ---- 面向对象之多态(向上转型与向下转型)

热门文章

  1. 关于AD转换设计的一些经验总结(转载)
  2. ios -获取手机唯一imei码
  3. 淘宝客用户与订单的绑定
  4. (LDO)MX6207 低消耗电流高 PSRR 500mA CMOS LDO
  5. java使用poi实现导出表格模板
  6. shell脚本在linux中运行报错:: command not found: line 2:
  7. 2020年研究生考试,加油!
  8. 【天池龙珠计划寒假训练营】python学习笔记(四):利用Pandas分析美国选民总统喜好度
  9. 10.21.2010吉他课笔记
  10. 最新最全MySQL 8知识,关注这篇就够了!