标签:
数据结构-堆
堆(英语:Heap),是一种拥有像树那样的特殊数据结构,或者理解为具有优先级的树。它的特点是父节点的值大于(或小于)两个子节点的值(分别称为大顶堆和小顶堆)。它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等。堆通常是一个可以被看做一棵树的数组(或ArrayList)对象。常见的堆有二叉堆、二项堆、斐波那契堆等。
二叉堆(Binary heap)
二叉堆是一种特殊的堆,实为二叉树的一种;是完全二叉树或者是近似完全二叉树。二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆。
当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。
二项堆(Binomial heap)
二项堆是一种类似于二叉堆的堆结构。与二叉堆相比,其优势是可以快速合并两个堆,因此它属于可合并堆(mergeable heap)抽象数据类型的一种。
二项堆是指满足以下性质的二项树的集合:
每棵二项树都满足最小堆性质,即结点关键字大于等于其父结点的关键字
不能有两棵或以上的二项树有相同度数(包括度数为0)。换句话说,具有度数k的二项树有0个或1个。
以上第一个性质保证了二项树的根结点包含了最小的关键字。第二个性质则说明结点数为n的二项堆最多只有\log{n} + 1棵二项树。实际上,包含n个节点的二项堆的构成情况,由n的二进制表示唯一确定,其中每一位对应于一颗二项树。
二项树(Binomial trees)
二项树递归定义如下:
数为0的二项树只包含一个结点
度数为k的二项树有一个根结点,根结点下有k个子女,每个子女分别是度数分别为k-1, k-2, ..., 2, 1, 0的二项树的根
度数为k的二项树共有2^k个结点,高度为k。在深度d处有(n d)(二项式系数)个结点。
度数为k的二项树可以很容易从两颗度数为k-1的二项树合并得到:把一颗度数为k-1的二项树作为另一颗原度数为k-1的二项树的最左子树。这一性质是二项堆用于堆合并的基础。
斐波那契堆(Fibonacci heap)
斐波那契堆(Fibonacci heap)是树的集合。它比二项式堆具有更好的平摊分析性能,可用于实现合并优先队列。不涉及删除元素的操作有O(1)的平摊时间。 Extract-Min和Delete的数目和其它相比,较小时效率更佳。稠密图每次decrease key只要O(1)的平摊时间,和二项堆的O(lg n)相比是巨大的改进。
斐波纳契堆于1984年由Michael L. Fredman与Robert E. Tarjan提出,1987年公开发表。名字来源于运行时分析使用的斐波那契数。
斐波那契堆是由一组最小堆有序树构成的。每个节点的度数为其子节点的数目。树的度数为其根节点的度数。
斐波那契堆中的树都是有根的但是无序。每个节点x包含指向父节点的指针p[x]和指向任意一个子结点的child[x]。x的所有子节点都用双向循环链表链接起来,叫做x的子链表。子链表中的每一个节点y都有指向它的左兄弟的left[y]和右兄弟的right[y]。如果节点y是x仅有的子节点,则left[y]=right[y]=y。
斐波那契堆中所有树的根节点也用一个双向循环链表链接起来。
使用一个指针指向斐波那契堆中最小元素。
堆的基本操作
创建一个堆build
向堆中插入一个新元素、新节点insert
将新元素提升、降低使其符合堆的性质update
增加、减小节点的值、增加、减小关键字的值、提高、降低一个节点的键值decrease-key
获取当前堆顶元素的值get
查找最小(大)关键字所在节点、查找最小(大)的节点 Find minimum、Find maximum, find-min
使删除堆顶元素的堆再次成为堆heapify
删除(释放)最小(大)关键字所在节点 Delete minimum, delete-min
删除给定节点Delete
删除堆顶元素、根节点delete
合并两个堆merge
某些堆实现还支持其他的一些操作,如斐波那契堆支持检查一个堆中是否存在某个元素。
堆的应用
堆的最常见应用是堆排序,时间复杂度为O(N lg N)。如果是从小到大排序,用大顶堆;从大到小排序,用小顶堆。
标签:
原文地址:http://my.oschina.net/u/660460/blog/469987