Lauen_1

Stay foolish

C语言的堆区与栈区

数据结构中的最大二叉堆:

如图所示,它是一颗完全的二叉树,除了最后一层外都是填满的,堆的子女和父母的关系可以利用上标计算。

关于最大二叉堆的操作,有保持堆性质MAX-HEAPIFY,建立堆BUILD-MAX-HEAP过程。若需要使用二叉堆进行堆排序,则需要HEAP-EXTRA-MAX等。

堆保持的递归算法如下:

通过比较元素与左右子女的大小,判断有没有保持堆的要求。

下图为堆排序示例:

建立堆的过程如下:

堆排序过程如图:

高效的优先级队列使用二叉堆进行实现,如下为利用最大堆实现的最大优先级队列

优先级队列一般支持四项操作:1.插入;2.返回最大值(即取队首元素);3.返回并去掉最大值;4.将某x元素增大到k。

通过观察二叉堆,不难实现以上操作。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

从二叉堆说到二项堆及斐波那契堆

二叉堆(binary heap)

二项堆(binomial heap):

二项堆是满足下列性质的二项树构成:

  1. 二项树遵循最小堆原理(节点的关键字大于或者等于其父节点)。
  2. 对于任意非负整数k,在H中至少有一棵二项树的根具有度数k。

二项堆中的二项树的深度与节点的关系恰好符合组合,即二项式的系数。

先介绍下二项树:

二项树有如下性质:

  1. 若有二项树Bk,其节点为2k个。
  2. 树的高度为k
  3. 深度i处恰好有组合个节点
  4. 根的度数为k,大于其他节点。并且根的子女从左到右分别是k-1,k-2…..0。

对于一个二项树有如下结构

按照后续遍历获得的顺序

二项堆的表示:

二项堆的主要操作:

  1. 寻找最小关键字
    最小关键字均在根节点,故其最多为lg n + 1
  2. 合并两个堆


  3. 插入节点
    构造一个单节点的树,然后合并两棵二项树
  4. 抽取最小关键字

    一个二项堆H,具有最小关键字的X被去掉,X子女逆转,然后合并
  5. 减小关键字的值
  6. 删除关键字

    暂时略

然后是斐波那契堆(Fibonacci Heaps)

相对于二项堆,斐波那契堆在不涉及删除元素的操作时,仅需要O(1)的平摊时间。

Fibonacci Heap在EXRTRACT-MINDELETE操作的数目较小。

最小生成树寻找单源最短路径时对每一条边会调用DECREASE-KEY,即利用优先级队列,

其O(1)的平摊时间对于O(lgn)来说提升很大。但是斐堆不如二叉堆来得实用。

 

斐波那契堆由一组最小堆有序树组成,但是堆中的树不一定是二项树。

此堆中的树都是有根而无序的

主要操作:

  1. 插入一个节点

  2. 抽取最小值

  3. 减小关键字

 

关于可合并堆的总结:

可合并堆支持的7种操作:

  1. 创建新堆
  2. 插入元素x
  3. 返回堆中最小或者最大的元素
  4. 删除最小或者最大元素
  5. 合并两个堆
  6. 将关键字值k赋予堆中节点
  7. 删除堆中结点

若不需要合并操作,那二叉堆已经很符合要求,二叉堆的合并操作最坏运行时间为O(n),二项堆和斐波那契堆的合并就相对较快。

在Prim算法中,性能取决于队列Q的实现,若用二项堆来实现Q,

BUILD-MIN-HEAP初始化为O(V)

EXTRACT-MIN需要O(lgV)次,运行V次,所以时间为O(VlgV)

还有E次DECREASE-KEY操作,单次为O(lgV)

所以总的时间O(VlgV + ElgV) = O(ElgV)

若使用斐波那契堆,时间可以减少到O(E+VlgV)

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2015-07-28 21:10  Lauen_1  阅读(200)  评论(0编辑  收藏  举报

导航