【数据结构】优先队列,堆
2016-04-27 19:21
260 查看
转载请注明原作者网址:http://blog.chinaunix.net/uid-20723500-id-134604.html
以操作系统对任务队列的处理原理提出来优先队列这个概念,在操作系统对任务的调度中,任务队列并不是简单的FIFO形式,而是以一定的优先级被调用的,这个队列就是优先队列,调度上带有级别区分的队列。
优先队列中至少要存在两种操作:insert和deletemin,前者对应着元素入队,后者对应于出队。
可以以很多方式实现优先队列,比如链表,这样插入操作只需要O(1)的时间,但是删除最小元的时间为O(N),也可以用二叉查找树,这样两种操作的平均运行时间都为O(logN).
对于优先队列最普遍的实现是:二叉堆。
堆是一棵从左到右填满的二叉树,当然底层例外,堆可以由简单的数组来表征,对于数组位置i上的元素,它的左孩子在2i上,右孩子在2i+1上,父亲则在[i/2]上,对于堆,为了便于上述两种操作的执行,定义一种堆序性质,即:在一个堆中,对于每一个节点X,X父亲的关键字小于等于X的关键字,根结点除外。
这样我们可以给出一些基本的堆操作的算法:
1.INSERT
思路是基于一种“上滤”的策略,设堆为H,待插入的元素为X,首先在size+1的位置建立一个空穴,然后比较X和空穴的爸爸的大小,把“大的爸爸”换下来,以此推进,最后把X放到合适的位置。
2.DELETEMIN
与上面的上滤对应,这将是一种“下滤”的策略,就是逐层推进,把较小的孩子换上来,这里面有个小的问题在具体算法实现上要注意,设堆的最后一个元素是L,在推进到倒数第二层时,将导致最后一层的某个孩子被换上去而产生一个洞,这时候为了保持堆的结构,必须把最后一个元素运过去补上,此时就存在一个问题,如果L比那个孩子小的话就不能保证堆序的性质了,所以在程序中要加一个if语句来进行这个边界条件的处理,还是那句话,对于一个完整的程序,算法是重要的一方面,而对算法边界问题的处理则是更重要的一方面。
堆还有其他一些操作,不详细笔记了。
最后在说一个堆的应用:
场景:求N个元素的第k个小的元素
算法1:将N个元素排序,取出第k个 O(N)
算法2:取出N个元素的前k个进行排序,然后依次取出N-k个元素,每一个元素都和第k个元素比较,如果比它小,那就把第k个元素删除,然后将该元素插入到适当的位置,重新组成k个元素 O(NK)
算法3:使用堆,使用这N个元素构造堆(O(N)),然后进行k次deletemin(O(klogN)),总的运行时间
O(N+klogN)。当k较大时这个时间为O(klogN),对于小的k值为O(N).
以操作系统对任务队列的处理原理提出来优先队列这个概念,在操作系统对任务的调度中,任务队列并不是简单的FIFO形式,而是以一定的优先级被调用的,这个队列就是优先队列,调度上带有级别区分的队列。
优先队列中至少要存在两种操作:insert和deletemin,前者对应着元素入队,后者对应于出队。
可以以很多方式实现优先队列,比如链表,这样插入操作只需要O(1)的时间,但是删除最小元的时间为O(N),也可以用二叉查找树,这样两种操作的平均运行时间都为O(logN).
对于优先队列最普遍的实现是:二叉堆。
堆是一棵从左到右填满的二叉树,当然底层例外,堆可以由简单的数组来表征,对于数组位置i上的元素,它的左孩子在2i上,右孩子在2i+1上,父亲则在[i/2]上,对于堆,为了便于上述两种操作的执行,定义一种堆序性质,即:在一个堆中,对于每一个节点X,X父亲的关键字小于等于X的关键字,根结点除外。
这样我们可以给出一些基本的堆操作的算法:
1.INSERT
思路是基于一种“上滤”的策略,设堆为H,待插入的元素为X,首先在size+1的位置建立一个空穴,然后比较X和空穴的爸爸的大小,把“大的爸爸”换下来,以此推进,最后把X放到合适的位置。
2.DELETEMIN
与上面的上滤对应,这将是一种“下滤”的策略,就是逐层推进,把较小的孩子换上来,这里面有个小的问题在具体算法实现上要注意,设堆的最后一个元素是L,在推进到倒数第二层时,将导致最后一层的某个孩子被换上去而产生一个洞,这时候为了保持堆的结构,必须把最后一个元素运过去补上,此时就存在一个问题,如果L比那个孩子小的话就不能保证堆序的性质了,所以在程序中要加一个if语句来进行这个边界条件的处理,还是那句话,对于一个完整的程序,算法是重要的一方面,而对算法边界问题的处理则是更重要的一方面。
堆还有其他一些操作,不详细笔记了。
最后在说一个堆的应用:
场景:求N个元素的第k个小的元素
算法1:将N个元素排序,取出第k个 O(N)
算法2:取出N个元素的前k个进行排序,然后依次取出N-k个元素,每一个元素都和第k个元素比较,如果比它小,那就把第k个元素删除,然后将该元素插入到适当的位置,重新组成k个元素 O(NK)
算法3:使用堆,使用这N个元素构造堆(O(N)),然后进行k次deletemin(O(klogN)),总的运行时间
O(N+klogN)。当k较大时这个时间为O(klogN),对于小的k值为O(N).
相关文章推荐
- 折半插入排序
- 【数据结构】 栈
- 用Navicat进行数据结构同步操作
- Java数据结构--排序
- 数据结构中哈夫曼树水题代码
- 直接插入排序
- HashMap的元素hash散列均匀必要性及算法优化
- C/C++数据结构
- 【数据结构】【面试题】找N个数据中最大的K个数据
- 【数据结构】用模版实现大小堆、实现优先级队列,以及堆排序
- 【数据结构】将一组数据升序排序(利用堆排序)
- 数据结构--优先级队列
- 数据结构和算法 c#– 1.单项链表
- 字符串匹配KMP算法
- 数据结构与算法——图的邻接表表示法类的C++实现
- 算法与数据结构(二) 基于链表的队列
- 数据结构与算法习题汇总(4)
- 数据结构 - 栈的顺序实现
- 数据结构之链表学习笔记
- 【数据结构】找出N个数据中最大的前k个数据(利用堆排序)