斐波那契堆是一种高级的堆结构,建议与二项堆一起食用效果更佳。

斐波那契堆是一个摊还性质的数据结构,很多堆操作在斐波那契堆上的摊还时间都很低,达到了θ(1)的程度,取最小值和删除操作的时间复杂度是O(lgn)。

斐波那契堆的关键操作我觉得是合并树和级联剪切。下面我简要地说一些关于这两个方法的体会。

斐波那契堆深度的增加应该就是通过合并树(consolidate)这个操作,如果没有剪切的影响,那么consolidate后的堆非常类似与二项堆。

级联剪切操作则是减小堆深度的操作,我在学习的时候一直有个问题,就是为什么级联剪切一定要失去第二个子结点时才开始剪切?为什么恰恰是二,而不是第三个或其他数?后来我看到一个大佬的博客写的是,这样可以尽量保证斐波那契堆可以类似于二项堆,防止“越剪越乱”。这个解释也是目前我最接受的。

所以可以看到的是斐波那契堆其实可以看做一个宽松的二项堆。

代码如下:(仅供参考)

  1. class FibHeap {
  2. private :
  3. struct Node {
  4. Node * parent;
  5. Node * child;
  6. Node * left;
  7. Node * right;
  8. int key;
  9. int degree; //degree of children
  10. bool mark; //whether lose any child
  11. Node() : parent(nullptr), child(nullptr), left(this), right(this),
  12. key(), degree(), mark(false) {}
  13. };
  14. private :
  15. Node * min; //pointer to the minimum node of heap
  16. int n;
  17. private :
  18. void listAdd(Node * &r, Node * p);//add p to r
  19. void listdelete(Node * p);
  20. void listUnion(Node * x, Node * y);//add x and y
  21. int Dn() {return (log2(n) + );} //当所有根都合并到一棵树上时,dn最大,为log2(n), 参考二项树
  22. void consolidate();
  23. void heapLink(Node * y, Node * x);
  24. void cut(Node * x, Node * y);
  25. void cascadingCut(Node * y);
  26. Node * search(Node * r, int k);//search is not good in heap
  27. public :
  28. FibHeap() : min(nullptr), n() {}
  29. void insert(int k);
  30. int extractMin(); //get minimum node and delete it
  31. int minimum() {return min->key;}
  32. void decreaseKey(Node * x, int k);
  33. void remove(int k);
  34. void heapUnion(FibHeap &b);
  35. bool search(int k) {return (search(min, k) == nullptr ? false : true);}
  36. bool empty() {return n == ;}
  37. };
  38.  
  39. void FibHeap::listAdd(Node * &r, Node * p) {
  40. if (r == nullptr) {
  41. r = p;
  42. r->left = r;
  43. r->right = r;
  44. }
  45. else {
  46. Node * x = r; //去引用
  47. p->right = x->right;
  48. p->left = x;
  49. x->right->left = p;
  50. x->right = p;
  51. }
  52. }
  53.  
  54. void FibHeap::listdelete(Node * p) {
  55. p->left->right = p->right;
  56. p->right->left = p->left;
  57. }
  58.  
  59. void FibHeap::listUnion(Node * x, Node * y) {
  60. if (x == nullptr)
  61. x = y;
  62. else {
  63. Node * tail = x->left;
  64. x->left->right = y;
  65. y->left->right = x;
  66. x->left = y->left;
  67. y->left = tail;
  68. }
  69. }
  70.  
  71. void FibHeap::insert(int k) {
  72. Node * p = new Node;
  73. p->key = k;
  74. listAdd(min, p);
  75. if (min->key > k) {
  76. min = p;
  77. }
  78. ++n;
  79. }
  80.  
  81. void FibHeap::heapLink(Node * y, Node * x) {
  82. listdelete(y);
  83. listAdd(x->child, y);
  84. ++x->degree;
  85. y->mark = false;
  86. }
  87.  
  88. void FibHeap::consolidate() {
  89. vector<Node*> a(Dn(), nullptr);
  90. Node *x, *y, *z;
  91. int d;
  92. Node * sentry = new Node;
  93. listAdd(min->left, sentry); //add a sentry
  94. for (x = min; x != sentry; x = z) {
  95. z = x->right; //防止x被link到y上,导致x-right无法指向正确的位置,所以先保存
  96. d = x->degree;
  97. while (a[d] != nullptr) {
  98. y = a[d];
  99. if (x->key > y->key)
  100. swap(x, y);
  101. heapLink(y, x);
  102. a[d] = nullptr;
  103. ++d;
  104. }
  105. a[d] = x;
  106. }
  107. min = nullptr;
  108. for (int i = ; i < a.size(); ++i) {
  109. if (a[i] != nullptr) {
  110. listAdd(min, a[i]);
  111. if (a[i]->key < min->key)
  112. min = a[i];
  113. }
  114. }
  115. delete sentry;
  116. }
  117.  
  118. int FibHeap::extractMin() {
  119. int ret = ;
  120. Node * p = min;
  121. if (p) {
  122. ret = p->key;
  123. if (p->child) {
  124. Node * x = p->child;
  125. Node * y = x->right;
  126. for (int i = ; i < p->degree; ++i) {
  127. listAdd(min, x);
  128. x->parent = nullptr;
  129. x = y;
  130. y = y->right;
  131. }
  132. }
  133. if (p->right == p) //the child of p is empty, and p is the only one in root list
  134. min = nullptr;
  135. else {
  136. min = p->right;
  137. listdelete(p);
  138. consolidate();
  139. }
  140. delete p;
  141. --n;
  142. }
  143. return ret;
  144. }
  145.  
  146. void FibHeap::cut(Node * x, Node * y) {
  147. listdelete(x);
  148. --y->degree;
  149. listAdd(min, x);
  150. x->parent = nullptr;
  151. x->mark = false;
  152. }
  153.  
  154. void FibHeap::cascadingCut(Node * y) {
  155. Node * z = y->parent;
  156. if (z) {
  157. if (y->mark == false)
  158. y->mark = true;
  159. else {
  160. cut(y, z);
  161. cascadingCut(z);
  162. }
  163. }
  164. }
  165.  
  166. void FibHeap::decreaseKey(Node * x, int k) {
  167. if (k >= x->key)
  168. return ;
  169. x->key = k;
  170. Node * y = x->parent;
  171. if (y && y->key > x->key) {
  172. cut(x, y);
  173. cascadingCut(y);
  174. }
  175. if (x->key < min->key)
  176. min = x;
  177. }
  178.  
  179. void FibHeap::remove(int k) {
  180. Node * p = search(min, k);
  181. if (p == nullptr)
  182. return ;
  183. decreaseKey(p, INT_MIN);
  184. extractMin();
  185. }
  186.  
  187. void FibHeap::heapUnion(FibHeap &b) { //can't use b any more
  188. if (b.min == nullptr)
  189. return ;
  190. listUnion(min, b.min);
  191. if (min->key > b.min->key)
  192. min = b.min;
  193. n += b.n;
  194. }
  195.  
  196. FibHeap::Node * FibHeap::search(Node * r, int k) {
  197. if (r == nullptr)
  198. return r;
  199. Node * x = r, *y;
  200. do {
  201. if (x->key == k)
  202. return x;
  203. else if (x->key < k) {
  204. y = search(x->child, k);
  205. if (y)
  206. return y;
  207. }
  208. x = x->right;
  209. } while (x != r);
  210.  
  211. return nullptr;
  212. }

fibonacci-Heap(斐波那契堆)原理及C++代码实现的更多相关文章

  1. 斐波那契堆(一)之 图文解析 和 C语言的实现

    概要 本章介绍斐波那契堆.和以往一样,本文会先对斐波那契堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现:实现的语言虽不同,但是原理如出一辙,选择其中之一进行了 ...

  2. 斐波那契堆(二)之 C++的实现

    概要 上一章介绍了斐波那契堆的基本概念,并通过C语言实现了斐波那契堆.本章是斐波那契堆的C++实现. 目录1. 斐波那契堆的介绍2. 斐波那契堆的基本操作3. 斐波那契堆的C++实现(完整源码)4.  ...

  3. 斐波那契堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了斐波那契堆,本章给出斐波那契堆的Java版本.还是那句老话,三种实现的原理一样,择其一了解即可. 目录1. 斐波那契堆的介绍2. 斐波那契堆的基本操作3. 斐波那契堆 ...

  4. 斐波那契堆(Fibonacci heap)原理详解(附java代码实现)

    前言 斐波那契堆(Fibonacci heap)是计算机科学中最小堆有序树的集合.它和二项式堆有类似的性质,但比二项式堆有更好的均摊时间.堆的名字来源于斐波那契数,它常用于分析运行时间. 堆结构介绍 ...

  5. 基于visual Studio2013解决算法导论之045斐波那契堆

     题目 斐波那契堆 解决代码及点评 // 斐波那契堆.cpp : 定义控制台应用程序的入口点. // #include<iostream> #include<cstdio> ...

  6. 笔试算法题(46):简介 - 二叉堆 & 二项树 & 二项堆 & 斐波那契堆

    二叉堆(Binary Heap) 二叉堆是完全二叉树(或者近似完全二叉树):其满足堆的特性:父节点的值>=(<=)任何一个子节点的键值,并且每个左子树或者右子树都是一 个二叉堆(最小堆或者 ...

  7. 10、end关键字和Fibonacci series: 斐波纳契数列

    # Fibonacci series: 斐波纳契数列 # 两个元素的总和确定了下一个数 a, b = 0, 1 #复合赋值表达式,a,b同时赋值0和1 while b < 10: print(b ...

  8. [LeetCode] Fibonacci Number 斐波那契数字

    The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such th ...

  9. fibonacci数列-斐波那契数列-python编程

    未完待续~ 了解fibonacci数列: 斐波纳契数列(Fibonacci Sequence),又称黄金分割数列. 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610 ...

随机推荐

  1. PAT 2018 秋

    A 1148 Werewolf - Simple Version 思路比较直接:模拟就行.因为需要序列号最小的两个狼人,所以以狼人为因变量进行模拟. #include <cstdio> # ...

  2. [XNUCA2019Qualifier]EasyPHP

    0x00 知识点 预期解中知识点: htaccess生效 如果尝试上传htaccess文件会发现出现响应500的问题,因为文件尾有Just one chance 这里采用# \的方式将换行符转义成普通 ...

  3. input自动填入密码以后变成白色和黄色的解决办法

    问题描述: 1.谷歌自动输入账号密码以后颜色变成黄色: 解决办法: 加样式: input:-webkit-autofill { background: red !important; color: # ...

  4. POJ 1663:Number Steps

    Number Steps Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13664   Accepted: 7378 Des ...

  5. MySQL 插入 中文数据乱码解决

    问题描述: 1.在命令行中进行插入,没有问题.但是显示存在部分乱码 2.在JDBC中插入成功.中文是直接以“??”形式显示. 通过Navicat客户端查看 与在网页中看到的一一致,说明读取没有问题,问 ...

  6. 使用Map,统计字符串中每个字符出现的次数

    package seday13; import java.util.HashMap; import java.util.Map; /** * @author xingsir * 统计字符串中每个字符出 ...

  7. 文献阅读报告 - Situation-Aware Pedestrian Trajectory Prediction with Spatio-Temporal Attention Model

    目录 概览 描述:模型基于LSTM神经网络提出新型的Spatio-Temporal Graph(时空图),旨在实现在拥挤的环境下,通过将行人-行人,行人-静态物品两类交互纳入考虑,对行人的轨迹做出预测 ...

  8. {转}理解HTTP/304响应

    源文(英):http://www.telerik.com/blogs/understanding-http-304-responses 中文译文:http://www.cnblogs.com/ziyu ...

  9. 干货 | DRDS 与TiDB浅析

    干货 | DRDS 与TiDB浅析 北京it爷们儿 京东云开发者社区  4月17日 在谈论数据库架构和数据库优化的时候,会常听到"分库分表"."分片".&quo ...

  10. JavaScript学习总结(六)

    我们知道,JavaScript共由三部分组成:EMCAScript(基本语法).BOM(浏览器对象模型).DOM. 在浏览器对象模型中,把浏览器的各个部分都用了一个对象进行描述,如果我们要操作浏览器的 ...