heap在STL中并不属于容器组建,而且作为priority queue的助手,你可以在<algorithms>
中找到关于heap的算法,如
- make_heap
- is_heap
- pop_heap
- push_heap
- sort_heap
在进行heap的分析之前,我们先了解一下priority queue(优先队列)
许多应用程序需要处理有序的元素,但不一定要求它们全部有序,有时候我们只想处理优先级最高的元素(例如基于优先级的调度器),这样,就要求一个能够
- 删除最大元素
- 插入元素
的数据结构,我们称其为priority queue,实现priority queue的合适做法是使用binary heap,所谓的binary heap就是一种完全二叉树,因此我们可以用数组来实现它,例如下面的例子
用数组表示就是
1 | {1,2,3,4,5} |
有序化
前面也提到了,priority queue是有序的,而且可以删除最大的元素,然后插入元素依旧可以保持有序,其中的奥秘就是在进行删除和插入的操作的时候,priority queue会按照一定的规则进行有序化
上浮
如果堆的有序状态因为某个节点变得比它的父节点大而被打破,例如在数组后面插入一个很大很大的节点,那么就要交换该节点和其父节点,然后,交换之后,仍旧可能大于父节点,然后继续交换,这种行为称为上浮
下沉
和上浮相反
push_heap
1 | template <class _RandomAccessIterator> |
pop_heap
值得注意的是,虽然是pop_heap
,但并没有在操作结束之后把元素给删除,而是将其移动到容器末尾,然后再由用户决定是否删除
1 | template <class _RandomAccessIterator> |
注:{1,2,3,4,5,6},数组长度为6,3的下标为2,3只有左节点6,2 * 2 + 2 = 6, 6等于数组长度,故3没有右节点,如果大于数组长度,说明3没有左节点
sort_heap
1 | template <class _RandomAccessIterator> |
这个就很简单,既然我们知道,pop_heap
能够将heap的根节点(也就是heap的最大节点)移动到末尾,那么只要对堆不断进行pop_heap
操作,然后缩小pop_heap
所操作的的范围,就能获取有序的数据集
make_heap
1 | template <class _RandomAccessIterator> |
也就是对当前的数组不断地进行调整,然后得到一个heap