堆在我们做算法时应该有映像吧,分为大根堆,小根堆。
STL中的其实是对堆有实现的,使得我们可以直接拿来用。
相关的函数是make_heap();push_heap();pop_heap();sort_heap();
make_heap
make_heap(first,end,cmp);参数有3个,第一个为堆建立堆的第一个元素,第二个为最后一个元素的后面一个位置,第三个为比较函数。
这个函数的第一和第二个参数的形式决定了建立堆必须是连续的内存分配形式,常见的就是vector和数组,别的像dequeue不常用我就不说了。
有start和end指定的区间是[start,end),也就是不包括end。对于vector很容易理解,start就是vector.begin(), end就是vector.end();
第三个函数是比较大小的函数,如果空着,默认建立大根堆。否则需要传入比较函数。
例子:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//上面的声明在后面的例子中自动包含,不重复写
bool mycmp(int a,int b){
return a > b;
}
int main(){
vector<int> demo;
int i=0;
for(i=0;i<20;i++){
demo.push_back(i);
}
//建大根堆
make_heap(demo.begin(),demo.end());
out << "big root:" <<endl;
for(i=0;i<20;i++){
cout<<demo[i] << ",";
}
cout << endl;
//建小根堆
make_heap(demo.begin(),demo.end(),mycmp);
cout << "small root:" <<endl;
for(i=0;i<20;i++){
cout<<demo[i] << ",";
}
cout << endl;
}
输出:
big root:
19,18,14,17,10,12,13,16,8,9,1,11,5,2,6,15,7,3,0,4,
small root:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, //这个怎么是线性有序的??因为这就是一个满足条件的小根堆,所以算法没有出问题的。
push_heap(start,end,cmp);
这个函数是建立在已经make_heap()的基础上,插入一个数据,使形成新堆,新插入的数据必须位于原有序的序列的最后,如果原来的是不成堆的,那么其运算结果也是不能保证成堆的。因为内部实现是只进行一个堆调整,把end之前的最后一个数加入堆。
各参数的意义同make_heap().
pop_heap(start,end,cmp);
这个函数是和push_heap相反的功能,他是把成堆队列的首个元素从队中拎出来,放到end之前的最后一个位置。其余元素从新调整成堆。
例子:
在前面make_heap()基础上:
int main(){
/*
......这一段同make_heap(),后面的在这基础上书写
*/
//加入一个新元素,重新排列成堆,若要加入两个元素,则要重复{push_back,push_heap}两次,不能全部push_back之后再push_heap.
//增加新元素
demo.push_back(3);
//加入堆
push_heap(demo.begin(),demo.end(),mycmp);
cout << "small root with new member:" <<endl;
for(i=0;i<21;i++){
cout<<demo[i] << ",";
}
cout << endl;
//弹出堆顶元素:0
pop_heap(demo.begin(),demo.end(),mycmp);
cout<<demo.back() << endl; //弹出的元素放在demo.end()的前面一格
demo.pop_back();
cout << "small root after pop a member:" <<endl;
for(i=0;i<20;i++){
cout<<demo[i] << ",";
}
cout << endl;
}
输出:
0,1,2,3,3,5,6,7,8,4,10,11,12,13,14,15,16,17,18,19,9,
0
small root after pop a member:
1,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
sort_heap()
我们知道在已经有序的堆中调一次pop_heap可以得到一个最值。如果不停调用pop_heap(每次的end参数要减掉1)直到全部弹出,那么就得到一个有序的队列。
原始若是大根堆,得到升序。原来若是小根堆,得到降序。
例子:
int main(){
/*
......这一段同push_heap()/pop_heap(),后面的在这基础上书写,0已被弹出。
......为什么老是以前面为基础,因为我只为所有函数写了一个例子,这样我就能重用一个打印输出。
*/
//sort members,big root->raise order
make_heap(&demo[0],&demo[20]);
sort_heap(demo.begin(),demo.end());
cout << "sort heap big root:" <<endl;
for(i=0;i<20;i++){
cout<<demo[i] << ",";
}
cout << endl;
//sort members,small root->decrese
make_heap(demo.begin(),demo.end(),mycmp);
sort_heap(demo.begin(),demo.end(),mycmp);
cout << "sort heap small root:" <<endl;
for(i=0;i<20;i++){
cout<<demo[i] << ",";
}
cout << endl;
}
输出:
sort heap big root:
1,2,3,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
sort heap small root:
19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,3,2,1,
==========
前面3个例子的合并的log(因为3个例子其实只有一份代码例子):
big root:
19,18,14,17,10,12,13,16,8,9,1,11,5,2,6,15,7,3,0,4,
small root:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
small root with new member:
0,1,2,3,3,5,6,7,8,4,10,11,12,13,14,15,16,17,18,19,9,
0
small root after pop a member:
1,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
sort heap big root:
1,2,3,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
sort heap small root:
19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,3,2,1,
==================================================
下面再记下priority_queue这个基于heap的STL模版。
头文件 #include <queue>
priority_queue<int> test;
test.push(2);
test.push(3);
test.push(1);
while(!test.empty()){
cout << test.top()<<endl;
test.pop();
}
输出
3
2
1
同样的脾气,默认是大的先出来
======
如果要小的先出来这么用:
priority_queue<int,vector<int>,greater<int> > test2;
test2.push(2);
test2.push(3);
test2.push(1);
while(!test2.empty()){
cout << test2.top()<<endl;
test2.pop();
}
输出:
1
2
3
=================
那么如果是自定义的类型呢,这么用:
struct Node
{
int x,y;
Node(int a = 0):x(a){}
//或者实现成成员函数
//bool operator< (const Node& node) const{
// return x < node.x;
//}
};
bool operator < (const Node& a,const Node& b){
return a.x < b.x;
}
priority_queue<Node> nodes;
nodes.push(Node(1));
nodes.push(Node(3));
nodes.push(Node(2));
while(!nodes.empty()){
cout << nodes.top().x<<endl;
nodes.pop();
}
输出:
3
2
1
或者这么用:
struct Node
{
int x,y;
Node(int a = 0):x(a){}
};
struct nodecmp
{
bool operator()(Node a,Node b){
return a.x > b.x ;
}
};
priority_queue<Node,vector<Node>,nodecmp> nodes2;
nodes2.push(Node(1));
nodes2.push(Node(3));
nodes2.push(Node(2));
while(!nodes2.empty()){
cout << nodes2.top().x<<endl;
nodes2.pop();
}
输出:
1
2
3
=====================
priority_queue还可以参考这个哥们的页面:
http://blog.csdn.net/sraing/article/details/6256302
=====================