文章目录
priority_queue 详解
优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。
priority_queue 是容器适配器,它提供常数时间的(默认)最大元素查找,对数代价的插入与释出。
注意:默认情况下priority_queue是大堆。
priority_queue 接口介绍及使用
在使用优先级队列时需要包含如下头文件:
include <queue>
using std::priority_queue
优先级队列默认是大根堆。下面的例子按大根堆进行演示,后面会讲解如何使用小根堆。
empty
判断当前优先级队列中是否为空,若为空返回1,否则返回0。
int main ()
{
std::priority_queue<int> mypq;
int sum (0);
for (int i=1;i<=10;i++)
mypq.push(i);
while (!mypq.empty())
{
sum += mypq.top();
mypq.pop();
}
std::cout << "total: " << sum << '\n';
return 0;
}
size
返回当前优先级队列中的元素个数。
int main ()
{
std::priority_queue<int> myints;
std::cout << "0. size: " << myints.size() << '\n';
for (int i=0; i<5; i++) myints.push(i);
std::cout << "1. size: " << myints.size() << '\n';
myints.pop();
std::cout << "2. size: " << myints.size() << '\n';
return 0;
}
push
将元素放入优先级队列中。
int main ()
{
std::priority_queue<int> mypq;
mypq.push(30);
mypq.push(100);
mypq.push(25);
mypq.push(40);
std::cout << "Popping out elements...";
while (!mypq.empty())
{
std::cout << ' ' << mypq.top();
mypq.pop();
}
std::cout << '\n';
return 0;
}
emplace
和push一样将元素放入优先级队列中。
int main ()
{
std::priority_queue<std::string> mypq;
mypq.emplace("orange");
mypq.emplace("strawberry");
mypq.emplace("apple");
mypq.emplace("pear");
std::cout << "mypq contains:";
while (!mypq.empty())
{
std::cout << ' ' << mypq.top();
mypq.pop();
}
std::cout << '\n';
return 0;
}
push和emplace的区别:
首先: push的操作可以直接用于emplace。
两者的区别主要体现在传入对象时。
- 直接传入对象
//假设栈内的数据类型是data
class data {
int a,b;
public:
data(int x, int y):a(x), b(y) {}
};
//push
data d(1,2);
S.push(d)
S.emplace(d);
先构造好对象后,再放入优先级队列。
- 在传入的时候构造对象
S.push(data(1,2))
S.emplace(data(1,2));
但是,emplace可以直接传入构造对象需要的元素,然后自己调用其构造函数,而push不行。
示例如下:
S.emplace(1,2)
emplace这样接受新对象的时候,自己会调用其构造函数生成对象然后放在容器内(比如这里传入1,2,它则会自动调用一次data(1,2))
而push,只能让其构造函数构造好了对象之后,再使用复制构造函数!
相当于emplace直接用原料造了一个,而push是造好了之后,再复制到自己家里,多了复制这一步。
所以emplace相对于push,会更节省内存。emplace这样接受新对象的时候,自己会调用其构造函数生成对象然后放在容器内(比如这里传入了1,2,它则会自动调用一次data(1,2))
pop
将堆顶的元素弹出优先级队列。
int main ()
{
std::priority_queue<int> mypq;
mypq.push(30);
mypq.push(100);
mypq.push(25);
mypq.push(40);
std::cout << "Popping out elements...";
while (!mypq.empty())
{
std::cout << ' ' << mypq.top();
mypq.pop();
}
std::cout << '\n';
return 0;
}
top
返回堆顶的元素。
int main ()
{
std::priority_queue<int> mypq;
mypq.push(10);
mypq.push(20);
mypq.push(15);
std::cout << "mypq.top() is now " << mypq.top() << '\n';
return 0;
}
swap
可以交换两个容器。
int main ()
{
std::priority_queue<int> foo,bar;
foo.push (15); foo.push(30); foo.push(10);
bar.push (101); bar.push(202);
foo.swap(bar);
std::cout << "size of foo: " << foo.size() << '\n';
std::cout << "size of bar: " << bar.size() << '\n';
return 0;
}
如何使用小根堆
priority_queue 的模板
template <class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
- T :需要存放的数据类型(int,double,string,类等)
- Container :使用什么样子的容器
- Compare : 传入仿函数,默认是less< int >
大根堆:
使用仿函数 less,将容器中的元素进行降序排列
priority_queue<int,vector<int>,less<int>> ret //降序队列,大顶堆
这样得到的ret容器是一个大根堆,C++默认优先级队列为大根堆,所以可以直接priority_queueret,但小根堆不行
小根堆:
使用仿函数 greater,将容器中的元素进行升序排列
priority_queue<int,vector<int>,greater<int>> ret //升序队列,小顶堆
这样得到的ret容器是一个小根堆
仿函数:
(部分代码已经简化)
less:
实质上也是一个类的模板,类中重载了运算符(),以实现两个元素的比较。因为是模板,所以可以支持多种元素类型的比较。
template <class T>
struct less {
bool operator() (const T& x, const T& y) const
{
return x<y;
}
}
greater:
template <class T>
struct greater {
bool operator() (const T& x, const T& y) const
{
return x>y;
}
}