斐波那契堆

    斐波那切堆数据结构有两种用途。第一种,它支持一系列操作,这些操作构成了所谓的“可合并堆”;第二种,斐波那切堆的一些操作可以在常数摊还时间内完成,这使得这种数据结构非常适合于需要频繁调用这些操作的应用。

可合并堆

    可合并堆是支持以下5种操作的一种数据结构,其中每个元素都有一个关键字:
- MAKE_HEAP():创建和返回一个新的不含任何元素的堆。
- INSERT(H, x):将一个已填入关键字的元素x插入堆H中。
- MINIMUM(H):返回一个指向堆H中具有最小关键字元素的指针。
- EXTRACT_MIN(H):从堆H中删除最小关键字的元素,并返回一个指向该元素的指针。
- UNION(H1, H2):创建并返回一个包含堆H1和堆H2中所有元素的新堆。堆H1和堆H2由这一操作“销毁”。
    除了以上可合并的操作外,斐波那契堆还支持以下两种操作:
- DECREASE_KEY(H, x, k):将堆H中元素x的关键字赋予新值k,假定新值k不大于当前的关键字。
- DELETE(H, x):从堆H中删除元素x。

斐波那切堆结构

    一个斐波那切堆是一系列具有最小堆序的有根树的集合。每棵树均遵循最小堆性质:每个结点的关键字大于或等于它的父结点的关键字。
    每个结点x包含一个指向它父结点的指针x.p和一个指向它的某一个孩子的指针x.child。x的所有孩子被链接成一个环形的双向链表,称为x的孩子链表。孩子链表中的每个孩子y具有指针y.left和y.right,分别指向y的左兄弟和右兄弟。如果y是仅有的一个孩子,则y.left=y.right。
    每个结点有另外两个属性。把结点x的孩子链表中的孩子数目储存在x.degree,在一个n个结点的斐波那切堆中任何结点的最大度数都有上界D(n),并且D(n) ≤ O(lgn)。布尔值属性x.mark指示结点x自从上一次成为另一个结点的孩子后,是否失去过孩子。新产生的结点是未标记过的,并且当结点x成为另一个结点的孩子时,它便成为未被标记结点。
    通过指针H.min来访问一个给定的斐波那切堆H,该指针指向具有最小关键字的树的根结点,把这个结点称为斐波那切堆的最小结点。如果不止一个根结点具有最小关键字,那么这些根结点的任何一个都有可能成为最小结点。如果一个斐波那切堆H是控的,那么H.min为NIL。
    在斐波那切堆中,所有树的根都用其left和right指针链成一个环形的双链表,该双链表称为斐波那切堆的根链表。指针H.min指向根链表中关键字最小的那个结点。
    斐波那切堆H中还有另一个属性:H.n,表示H中当前的结点数目。

斐波那切堆的相关操作

创建一个新的斐波那切堆

    创建一个新的斐波那切堆,MAKE_FIB_HEAP过程分配并返回一个斐波那切堆对象H,其中H.n=0和H.min=NIL,H中不存在树。

插入一个结点

    将结点x插入斐波那切堆H中,假定该结点已经被分配,x.key已经被赋值。

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

寻找最小结点

    斐波那切堆的最小结点可以通过指针H.min得到。

两个斐波那切堆的合并

    下面的过程合并斐波那契堆H1和H2,并在该过程中销毁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

抽取最小结点

    假定当一个结点从链表中移除后,留在链表中的指针要被更新,但是抽取出的结点中的指针并不改变。该代码还调用一个辅助过程CONSOLIDATE。

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

    FIB_HEAP_EXTRACT_MIN首先将最小结点的每个孩子变为根结点,并从根链表中删除该最小结点。然后通过把具体相同度数的根结点合并的方法来链接成根链表,直到每个度数至多只有一个根在根链表中。
    下一步是合并H的根链表,通过调用CONSOLIDATE(H)来减少斐波那切堆中树的数目。合并根链表的过程为重复执行以下步骤,直到根链表中的每一个根有不同的度数。
1. 在根链表中找到两个具有相同度数的根x和y。不失一般性,假定x.key≤y.key。
2. 把y链接到x:从根链表中移除y,调用FIB_HEAP_LINK过程,使y成为x的孩子。该过程将x.degree属性增1,并清除y上的标记。
    过程CONSOLIDATE使用一个辅助数组A[0..D(H.n)]来记录根结点对应的度数的轨迹。如果A[i]=y,那么当前的y是一个具有y.degree=i的根。

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]
    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 list of H
make y a child of x, incrementing x.degree
y.mark = FALSE

关键字减值

    假定从一个链表中移除一个结点不改变移除的结点的任何结构属性。

FIB_HEAP_DECREASE_KEY(H, x, k)
if k > x.key
  errornew key is greater then 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.mark = TRUE
  else
    CUT(H, y, z)
    CASCADING_CUT(H, z)

    CUT过程“切断”x与其父结点y之间的链接,使x成为根结点。
    我们使用mark属性来得到需要的时间界。该属性记录了每个结点的一小段历史。假定下面的步骤已经发生在结点x上:
1. 在某个时刻,x是根。
2. 然后x被链接到另一个结点(成为孩子结点)。
3. 然后x的两个孩子被切断操作移除。
    一旦失掉第二个孩子,就切断x与其父结点的链接,使它成为一个新的根。

删除一个结点

    假定在斐波那切堆中任何关键字的当前值均不为-∞。

FIB_HEAP_DELETE(H, x)
FIB_HEAP_DECREASE_KEY(H, x, -∞)
FIB_HEAP_EXTRACT_MIN(H)

    FIB_HEAP_DELETE把唯一的最小关键字-∞赋予x,将x变为斐波那切堆中最小的结点。然后FIB_HEAP_EXTRACT_MIN过程从斐波那切堆中移除x。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值