一.heap
在STL中,priority_queue(优先权队列)的底层机制是最大堆,因此有必要先来了解一下heap。heap采用完全二叉树的结构,当然不是真正的binary tree,因为对于完全二叉树,我们通常用一个数组来表示。
以下几个算法都是STL的泛型算法,包含在头文件algorithm里,priority_queue的push(),pop()都有直接调用它们。
1.push_heap算法
首先,将新元素插入到底层vector的end()处。为了满足最大堆原理(每个结点的值必须大于或等于其子结点的值),于是将新结点与其父亲结点比较,如果其值大于父亲结点,就交换父子结点,直到不需要交换或者它已经到达根结点为止。
2.pop_heap算法
因为作为最大堆,根结点即为最大值。交换vector首尾(first和last)元素,并重新调整[first,last-1)部分,也就是将“新根结点”跟其较大子结点交换,并持续下放,知道叶子结点为止。注意,pop_heap之后,最大元素只是被放在底部容器的最尾端,并没有被取走。若要取走,可用vector的pop_back()函数。
3.sort_heap算法
持续对整个heap做pop_heap操作,每次将操作范围从后向前缩减一个元素,于是我们得到一个递增序列。显然,排序后的heap不是一个合法的heap了。
4.make_heap算法
这个算法用来将数组转化成一个heap
二,heap(堆)简介
1)采用vector存储,是一颗完全二叉树(complete binary tree)的形式。
heap分为 max_heap 和 min_heap,前者最大权值在根,后者最小权值在根。
2)建立堆过程
vector中元素先调整为堆的形式。
插入元素时,将元素放到vector 的最后面end(),然后上溯调整堆。
3)heap算法 // #include <algorithm>
make_heap(first,last) //初建堆
push_heap(first,last) //插入元素,并调整为堆
pop_heap(first,last) //弹出元素,并调整为堆
sort_heap(first,last) //堆排序
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int a[9]={0,1,2,3,4,5,6,7,8,};
vector<int>ivec(a,a+9);
make_heap(ivec.begin(),ivec.end());
for(int i=0;i<ivec.size();i++)
printf("%d ",ivec[i]);
printf("\n");
ivec.push_back(7);
push_heap(ivec.begin(),ivec.end());
for(int i=0;i<ivec.size();i++)
printf("%d ",ivec[i]);
printf("\n");
pop_heap(ivec.begin(),ivec.end());
printf("%d\n",ivec.back());
ivec.pop_back();
for(int i=0;i<ivec.size();i++)
printf("%d ",ivec[i]);
printf("\n");
sort_heap(ivec.begin(),ivec.end());
for(int i=0;i<ivec.size();i++)
printf("%d ",ivec[i]);
printf("\n");
}
三,priority_queue 实例
#include<queue>
#include<algorithm>
#include<cstdio>
using namespace std;
int main(){
int a[9]={1,2,4,3,6,5,9,8,7};
priority_queue<int>ipq(a,a+9);
printf("size;%d\n",ipq.size());
for(int i=0;i<ipq.size();i++)
printf("%d ",ipq.top());
printf("\n");
while(!ipq.empty()){
printf("%d ",ipq.top());
ipq.pop();
}
printf("\n");
}
1)STL里面默认用的是 vect or . 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。如果要用到小顶堆,则一般要把模板的三个参数都带进去。STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆
#include <iostream>
#include <queue>
#include <cstdlib>
#include<cstdio>
using namespace std;
int main(){
priority_queue<int, vector<int>, greater<int> > q;
for( int i= 0; i< 10; ++i ) q.push(i);
while( !q.empty() ){
printf("%d ",q.top());
q.pop();
}
printf("\n");
return 0;
}
2)5)自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。但此时不能像基本类型这样声明priority_queue<Node, vector<Node>, greater<Node> >;原因是 greater<Node> 没有定义,如果想用这种方法定义则可以按如下方式: