第五部分 高级数据结构
第19章 斐波那契堆
两种用途:
1. 支持一系列操作,这些操作构成了所谓的“可合并堆”;
2. 这些操作可以在常数摊还时间内完成,使得非常适合于需要频繁调用这些操作的应用;
1. 斐波那契堆结构
一个斐波那契堆是一系统具有最小堆序的有根树的集合。也就是说,每棵树均遵循最小堆性质:每个结点的关键字大于或等于它的父结点的关键字。
每个结点x包含一个指向它父结点的指针x.p和一个指向它的某一个孩子的指针x.child。x的所有孩子被链接成一个环形的双向链表,称为x的孩子链表。孩子链表中的每个孩子y均有指针y.left和y.right,分别指向y的左兄弟和右兄弟。如果y是仅有的一个孩子,则y.left = y.right =y。
结点x的孩子链表中的孩子数目储存在x.degree。布尔值属性x.mark指示结点x自从上一次成为另一个结点的孩子后,是否失去过孩子。
通过指针H.min来访问一个给定的斐波那契堆H,该指针指向具有最小关键字的树的根结点,我们把这个结点称为斐波那契堆的最小结点。
如果一个斐波那契堆H是空的,那个H.min为NIL。
H.n表示H中当前的结点数目。
势函数
t(H)表示H中根链表中树的数目,m(H)表示H中已标记的结点数目。H的势函数如想:
Φ(H) = t(H) + 2m(H)
2. 可合并堆操作
创建一个新的斐波那契堆
创建一个空的H,Make-Fib-Heap分配并返回一个Fib对象H,其中H.n = 0和H.min = NIL,H中不存在树。
因为 t(H) =0和m(H) =0,Φ(H) = 0。因此,Make-Fib-Heap的摊还代价等于它的实际代价O(1)
插入一个结点
Fib-Heap-Insert(H, x)
x.degree = 0
x.p = NIL
x.child = NIL
x.mark = FALSE
if H.min == NIL
create a root list for H containing just x
H.min = x
else
insert x into H's root list
if x.key < H.min.key
H.min = x
H.n = H.n + 1
t(H’) = t(H’) + 1
m(H’) = m(H)
势的增加量为: ( t(H) + 1 + 2m(H)) - ( t(H) + 2m(H)) = 1
实际代价为O(1),因此摊还代价为O(1) + 1 = O(1)
寻找最小结点
最小结点可通过H.min得到。因此,可以在O(1)的实际代价内找到最小结点。H的势没有发生变化,因此该操作的摊还代价等于它的初阶代价O(1)。
两个斐波那契堆的合并
将H1和H2的根链表链接,然后确定新的最小结点。之后,销毁H1和H2,表示H1和H2的对象将不再使用。
Fib-Heap-Union(H1, H2)
H = Make-Fib-Heap()
H.min = H1.min
concatenate the root list of H2 with the root list of H
if (H1.min == NIL) or (H2.min != NIL and H2.min.key < H1.min.key)
H.min = H2.min
H.n = H1.n + H2.n
return H
势函数变化为:
Φ(H) - (Φ(H1)+Φ(H2)) = (t(H)+2m(H)) - ((t(H1)+2m(H1)) + (t(H2)+2m(H2))) = 0
摊还代价等于它的实际代价O(1)
抽取最小结点
Fib-Heap-Extract-Min(H)
z = H.min
if z != NIL
for each child x of z
add x to the root list of H
x.p = NIL
remove z from the root list of H
if z == z.right
H.min = NIL
else
H.min = z.right
Consolidate(H)
H.n = H.n - 1
return z
Consolidate(H)
let A[0..D(H.n)] be a new array
for i = 0 to D(H.n)
A[i] = NIL
for each node w in the root list of H
x = w
d = x.degree
while A[d] != NIL
y = A[d] // another node with the same degree as x
if x.key > y.key
exchange x with y
Fib-Heap-Link(H, y, x)
A[d] = NIL
d = d + 1
A[d] = x
H.min = NIL
for i = 0 to D(H.n)
if A[i] != NIL
if H.min == NIL
create a root list for H containing just A[i]
H.min = A[i]
else
insert A[i] into H's root list
if A[i].key < H.min.key
H.min = A[i]
Fib-Heap-Link(H, y, x)
remove y from the root list of H
make y a child of x, incrementing x.degree
y.mark = FALSE
摊还时间为O(lgn)
3.关键字减值和删除一个结点
Fib-Heap-Decrease-Key(H, x, k)
if k > x.key
error "new key is greater than current key"
x.key = k
y = x.p
if y != NIL and x.key < y.key
Cut(H, x, y)
Cascading-Cut(H, y)
if x.key < H.min.key
H.min = x
Cut(H, x, y)
remove x from the child list of y, decrementing y.degree
add x to the root list of H
x.p = NIL
x.mark = FALSE
Cascading-Cut(H, y)
z = y.p
if z != NIL
if y.mark = FALSE
y.makr = TRUE
else
Cut(H, y, z)
Cascading-Cut(H, z)
摊还时间为O(1)
4. 删除一个结点
Fib-Heap-Delete(H, x)
Fib-Heap-Decrease-Key(H, x, -∞)
Fib-Heap-Extract-Min(H)
摊还时间为O(lgn)