斐波那契堆

本章内容:

一 斐波那契堆结构

二 可合并堆操作

三 关键字减值和删除一个结点

四 最大度数的界

 

可合并堆支持以下5种操作:

MAKE-HEAP():创建和返回一个新的空堆

INSERT(H,x):将一个含关键字的元素x插进堆H中

MINIMUN(H):返回一个指向堆H中具有最小关键字元素的指针

EXTRACT-MIN(H):从堆中删除最小关键字的元素,并返回一个指向该元素的指针

UNION(H1,H2):创建并返回一个包含2个堆中所有元素的新堆,并销毁原来2个堆

 

斐波那契堆除了以上的堆操作之外还支持以下2种操作:

DECREASE-KEY(H,x,k):将堆H中元素x的关键字赋予新值k,假定新值k不大于当前的关键字。

DELETE(H,x):从堆中删除元素x

 

可合并堆的运行时间

 

一 斐波那契堆结构

 

1. 斐波那契堆是一系列具有最小堆序的有根树的集合,每棵树遵循最小堆的性质,即每个结点的关键字大于或等于父结点的关键字。

2. 每个结点x包含一个指向父结点的指针x.p和一个指向它的某一个孩子的指针x.child。x的所有孩子被链接成一个双向的链表,称为x的孩子链表。每个孩子y有指针y.left和y.right。如果y是仅有的一个孩子,则y.left = y.right = y。

3. x.degree记录孩子的个数。

4. x.mark指示结点x自从上一次成为另一个结点的孩子后,是否失去过孩子。新产生的结点是未被标记的。

5. H.min指向具有最小关键字的树的根结点。

6. H.n记录堆中所有结点的数目。

7. 所有树的根用其left和right链成一个环形的双链表,称为根链表。

8. 势函数:

t(H)表示根链表中树的数目,m(H)表示已标记的结点数目。

9. 一个例子

 

二 可合并堆的操作

 

1. 插入一个结点x,x已经被分配且x.key已经被赋值:

该操作势的增加量为:

实际代价为O(1),摊还代价为O(1) + 1 = O(1)

2. 两个斐波那契堆的合并:

势函数变化为:

所以实际代价为O(1)

3. 抽取最小结点:

 

该过程首先将最小结点的每个孩子变成根结点,并从链表中删除该结点,然后通过CONSOLIDATE把具有相同度数的根结点合并来链接成新的根链表,直到每个度数至多只有一个根在根链表中。

合并相同度数的根结点:

把根结点y链接到x成为x的孩子:

4~14行遍历根链表,对根链表中的每个结点x,查找辅助数组A,如果没有相同度数的结点,则将该结点标记为该度数的结点。如果已经存在,则将key值大的结点链接到小的上面,使x的degree加1,并继续判断是否有度数相同的结点。这样14行之后A中记录的根链表将没有重复度数的根结点。然后15~23行利用辅助数组A重建根链表。

 

抽取最小结点操作的摊还代价最多为O(D(n)),即与最大度数成正比。后面将会证明D(n) = O(lg n),所以该操作的摊还代价为O(lg n).

 

三 关键字减值和删除一个结点

 

1. 关键字减值:

 

减值后如果没有违反最小堆序则无需改变,否则要在6~7行进行切断和级联切断操作。

回顾前面提到的结点的一个属性mark,在该结点成为根结点的时候置为false,在成为一个孩子结点并且失去一个孩子后置为true。CUT函数首先切断x与父结点y的链接,并将x置为根结点,然后对其父结点y进行级联切断。这里的规则是如果一个结点的mark为true并且失去一个孩子就要将其与父结点切断,意思就是当一个非根结点失去第二个孩子(失去第一个孩子时mark值变为true)的时候将其与父结点切断。CASCADING-CUT就是通过递归操作一直往上切断,直到遇到根结点或者遇到一个未被标记的结点并将mark置为true。

可以证明FIB-HEAP-DECREASE-KEY的摊还代价为O(1).

 

2. 删除一个结点:

将最小关键字负无穷赋予x后即可通过FIB-HEAP-EXTRACT-MIN将其移除。

 

四 最大度数的界

 

1. 可以证明一个具有n个结点的斐波那契堆中任意结点的度数的上界D(n)为O(lg n),从而可以得到FIB-HEAP-EXTRACT-MIN和FIB-HEAP-DELETE操作摊还时间为O(lg n)

 

posted @ 2014-04-22 08:31  Jolin123  阅读(751)  评论(0编辑  收藏  举报