**斐波那契堆**（英語：）是计算机科学中树的集合。它比二项堆具有更好的平摊分析性能，可用于实现合并优先队列。不涉及删除元素的操作有 {\displaystyle O(1)} 的平摊时间。 Extract-Min和Delete的数目和其它相比，较小时效率更佳。稠密图每次decrease key只要 {\displaystyle O(1)} 的平摊时间，和二项堆的 <mathO(log n)</math> 相比是巨大的改进。

斐波纳契堆于1984年由邁克爾·弗雷德曼与罗伯特·塔扬提出，1987年公开发表。名字来源于运行时分析使用的斐波那契数。

结构
--

斐波那契堆是由一组最小堆有序树构成的。每个节点的度数为其子节点的数目。树的度数为其根节点的度数。

斐波那契堆中的树都是有根的但是无序。每个节点*x*包含指向父节点的指针*p[x]*和指向任意一个子结点的*child[x]*。x的所有子节点都用双向循环链表链接起来，叫做*x*的子链表。子链表中的每一个节点*y*都有指向它的左兄弟的*left[y]*和右兄弟的*right[y]*。如果节点*y*是*x*仅有的子节点，则*left[y]=right[y]=y*。

斐波那契堆中所有树的根节点也用一个双向循环链表链接起来。

使用一个指针指向斐波那契堆中最小元素。

操作
--

### 建立一个新的費波那契堆

此處範例中使用的程式語言為C

每个结点x的域

1. 父结点p[x]
2. 指向任一子女的指针child[x]——结点x的子女被链接成一个环形双链表，称为x的子女表
3. 左兄弟left[x]
4. 右兄弟right[x]——当left[x] = right[x] = x时，说明x是独子。
5. 子女的个数degree[x]
6. 布尔值域mark[x]——标记是否失去了一个孩子

```

//斐波那契结点ADT
typedef struct FibonacciHeapNode {
    int key;       //结点
    int degree;    //度
    FibonacciHeapNode *left;  //左兄弟
    FibonacciHeapNode *right; //右兄弟
    FibonacciHeapNode *parent; //父结点
    FibonacciHeapNode *child;  //第一个孩子结点
    bool marked;           //是否被删除第1个孩子
} FibNode;
```

对于一个给定的斐波那契堆H，可以通过指向包含最小关键字的树根的指针min[H]来访问，这个结点被称为斐波那契堆中的最小结点。如果一个斐波那契堆H是空的，则min[H] = NIL. 在一个斐波那契堆中，所有树的根都通过left和right指针链接成一个环形的双向链表，称为堆的根表。于是，指针min[H]就指向根表中具有最小关键字的结点。

```

//斐波那契堆ADT
typedef struct FibonacciHeap {
    int keyNum;   //堆中结点个数
    FibonacciHeapNode *min;//最小堆，根结点
    int maxNumOfDegree;   //最大度
    FibonacciHeapNode **cons;//指向最大度的内存区域
} FibHeap;
```

创建一个空的費波那契堆，过程MAKE-FIB-HEAP 分配并返回一个費波那契堆对象H；

```

//初始化一個空的Fibonacci Heap
FibHeap *FibHeapMake() {
    return calloc(1, sizeof(FibHeap));
}
 
//初始化節點x
FibNode * FibHeapNodeMake() {
    FibNode *x = (FibNode *)calloc(1, sizeof(FibNode));
    x->left = x->right = x;
    return x;
}
```

### 插入一个节点

创建一个仅包含一个节点的新的斐波纳契堆，然后执行堆合并。

### 查找最小的节点

由于用一个指针指向了具有最小值的根节点，因此查找最小的节点是簡單的操作。

### 合并两个斐波纳契堆

简单合并两个斐波纳契堆的根表。即把两个斐波纳契堆的所有树的根首尾衔接并置。

### 释放（删除）最小的节点

分为三步：

1. 查找最小的根节点并删除它，其所有的子节点都加入堆的根表，即它的子树都成为堆所包含的树；
2. 需要查找并维护堆的最小根节点，但这耗时较大。为此，同时完成堆的维护：对堆当前包含的树的度数从低到高，迭代执行具有相同度数的树的合并并实现最小树化调整，使得堆包含的树具有不同的度数。这一步使用一个数组，数组下标为根节点的度数，数组的值为指向该根节点指针。如果发现具有相同度数的其他根节点则合并两棵树并维护该数组的状态。
3. 对当前堆的所有根节点查找最小的根节点。

### 降低一个节点的键值

对一个节点的键值降低后，自键值降低的节点开始自下而上的迭代执行下述操作，直至到根节点或一个未被标记（marked）节点为止：

如果当前节点键值小于其父节点的键值，则把该节点及其子树摘下来作为堆的新树的根节点；其原父节点如果是被标记（marked）节点，则也被摘下来作为堆的新树的根节点；如果其原父节点不是被标记（marked）节点且不是根节点，则其原父节点被加标记。

如果堆的新树的根节点被标记（marked），则去除该标记。

### 删除节点

把被删除节点的键值调整为负无穷小，然后执行"降低一个节点的键值"算法，然后再执行"删除最小节点"算法。

参考文献
----

1. ↑  Fredman, Michael Lawrence; Tarjan, Robert E.  (PDF). Journal of the Association for Computing Machinery. 1987, **34** (3): 596–615  [2013-11-20]. doi:10.1145/28869.28874. （原始内容存档 (PDF)于2016-06-23）.

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
数据结构 |
| --- |
|  |
| 类型 | 
* 集合
* 容器

 |
|  |
| 抽象类型 | 
* 关联数组
	+ 多重关连数组（英语：）
* 列表
* 堆栈
* 队列
	+ 双端队列
* 优先队列
	+ 双端优先队列
* 集合
	+ 多重集
	+ 併查集
* 可持久化数据结构
	+ 线段树

 |
|  |
| 数组 | 
* 字串
* 位数组
* 环形缓冲器
* 动态数组
* 哈希表
* 哈希数组树（英语：）
* 稀疏矩阵

 |
|  |
| 链（英语：） | 
* 关联表（英语：）
* 链表
* 跳跃列表
* 松散链表（英语：）
* 异或链表

 |
|  |
| 树 | 
* 线段树
* 自平衡二叉查找树
* B树
* 二叉树
	+ AA树
	+ AVL树
	+ 红黑树
	+ 平衡树
	+ 伸展树
	+ 二叉查找树
* 堆
	+ 二叉堆
	+ 左偏树
	+ 二项堆
	+ 斐波那契堆
* R树
	+ R\*树
	+ R+树
	+ 希爾伯特R树（英语：）
* 希尔伯特前缀树
	+ 哈希树

 |
|  |
| 图 | 
* 有向图
* 有向无环图
* 二元决策图
* 无向图
* 确定性非循环有限自动机（英语：）

 |
|  |
| 数据结构术语 |

 |

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
计算机科学中的树 |
| --- |
|  |
| 二叉树 | 
* 二元搜尋樹
* 笛卡尔树
* MVP树
* Top tree（英语：）
* T树
* 线索二叉树

 |
|  |
| 自平衡二叉查找树 | 
* AA树
* AVL树
* 左倾红黑树
* 红黑树
* 替罪羊树
* 伸展树
* 树堆
* 加权平衡树

 |
|  |
| B树 | 
* B+树
* B\*树
* Bx树
* UB树
* 2-3树
* 2-3-4树
* (a,b)-树
* 跳舞樹（英语：）
* H树

 |
|  |
| 堆 | 
* 二叉堆
* 二项堆
* 斐波那契堆
* 左偏树
* 配对堆
* 斜堆
* 范恩德蟒蛇樹（英语：）

 |
|  |
| Trie | 
* 后缀树
* 基数树
* 三叉查找树
* X-快速前缀树
* Y-快速前缀树
* AC自动机

 |
|  |
| 二叉空间分割（BSP）树 | 
* 四叉树
* 八叉树
* *k*-d树
* 隐式*k*-d树
* VP树

 |
|  |
| 非二叉树 | 
* 指数树（英语：）
* 融合树（英语：）
* PQ树（英语：）
* SPQR树（英语：）

 |
|  |
| 空间数据分割树 | 
* R树
* R\*树
* R+树
* X树
* M树
* 線段樹 (儲存區間)
* 线段树 (区间查询)
	+ 可持久化线段树
* 希尔伯特R树
* 优先R树

 |
|  |
| 其他树 | 
* 散列日历
* 散列树
* 手指樹（英语：）
* 顺序统计树
* 度量樹（英语：）
* 覆蓋樹（英语：）
* BK树
* 二重連鎖樹（英语：）
* iDistance（英语：）
* Link-cut tree（英语：）
* Log-structured merge-tree（英语：）
* 树状数组
* 哈希树

 |

 |