一:斐波那契堆
1:特性
斐波那契堆同二项堆一样,也是一种可合并堆。斐波那契堆的优势是:不涉及删除元素的操作仅需要O(1)的平摊运行时间(关于平摊分析的知识建议看《算法导论》第17章)。和二项堆一样,斐波那契堆由一组树构成。这种堆松散地基于二项堆,说松散是因为:如果不对斐波那契堆做任何DECREASE-KEY 或 DELETE 操作,则堆中每棵树就和二项树一样;但是如果执行这两种操作,在一些状态下必须要破坏二项树的特征,比如DECREASE-KEY或DELETE 后,有的树高为k,但是结点个数却少于2k。这种情况下,堆中的树不是二项树。
与二项堆相比,斐波那契堆同样是由一组最小堆有序树构成。最小堆性质:每个结点的关键字大于等于父节点的关键字。但是斐波那契堆中的树都是有根而无序的,也就是说,单独的树满足最小堆特性,但是堆内树与树之间是无序的,如下图。
对于斐波那契堆上的各种可合并操作,关键思想是尽可能久地将工作推后。例如,当向斐波那契堆中插入新结点、删除结点或合并两个斐波那契堆时,并不去合并树,而是将这个工作留给EXTRACT-MIN操作。
看一下斐波那契堆的链表结构表示:
2:每个结点的域:
//斐波那契结点ADT
struct FibonacciHeapNode {
int key; //结点
int degree; //度
FibonacciHeapNode * left; //左兄弟
FibonacciHeapNode * right; //右兄弟
FibonacciHeapNode * parent; //父结点
FibonacciHeapNode * child; //第一个孩子结点
bool marked; //是否被删除第1个孩子
};
typedef FibonacciHeapNode FibNode;
1) 父节点*p
2) 指向任一子女的指针*child——结点x的子女被链接成一个环形双链表,称为x的子女表
3) 左兄弟*left
4) 右兄弟*right——当left[x] = right[x] = x时,说明x是独子。
5) 子女的个数degree[x]
6) 布尔值域mark[x]——标记是否失去了一个孩子
3:堆结构
对于一个给定的斐波那契堆H,可以通过指向包含最小关键字的树根的指针H.min来访问,这个结点被称为斐波那契堆中的最小结点。如果一个斐波那契堆H是空的,则H.min = NIL. 在一个斐波那契堆中,所有树的根都通过left和right指针链接成一个环形的双链表,称为堆的根表。于是,指针H.min就指向根表中具有最小关键字的结点。
指向根结点的堆结构体: