目录
前言
priority_queue的介绍
优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。
注意: 默认情况下priority_queue是大堆。
基本结构
关于优先级队列实际上就是一个堆,堆分为大根堆和小根堆
- 这里列举大根堆
关于堆这个数据结构我在【手撕数据结构】二叉树和堆这篇文章里已经详细讲解过,如果还不了解的可以去看看这篇文章
如何设置默认大小堆
这里我们提出一个叫仿函数的概念:
看看库里面的priority_queue

- 其实仿函数就是一个类,和容器适配器差不多,仿函数仿在哪里,我们知道函数调用都是通过()来标记这是一个函数,所以这个类里面就重载了()运算符
注意:
1.提供Greater(大于)是小根堆
2.提供Less(小于) 是大根堆
底层实现
仿函数的使用
cpp
template<class T, class Contain = vector<T>, class Compare = Less<T>>
class Priority_queue
{
Compare com;
- 定义一个仿函数对象com
cpp
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
- 这里就是使用对象的运算符重载()达到大小相比
向上调整算法
- 这个原理我也在以前的文章中讲过,这里就不再详细讲解了,请往上面的链接去看
cpp
void AdjustUp(int child)
{
int parent = (child - 1) / 2;
while (child > 0) //测试一下
{
if (com(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
向下调整算法
cpp
void AdjustDown(int parent)
{
int child = 2 * parent + 1;
while (child < _con.size())
{
if (child + 1 < _con.size() && com(_con[child], _con[child + 1]))
{
child++;
}
if (com(_con[parent], _con[child]))
{
swap(_con[parent], _con[child]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
其他接口
cpp
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
const T& top()
{
return _con[0];
}
bool empty()
{
return _con.empty();
}
int size()
{
return _con.size();
}
- 根据复用vector这个容器适配器接口就行, pop是堆的删除所以是删除堆顶,然后重新调整堆的特征结构
- 插入从最后插入,也是要调整结构。
- 具体原理图解看以前的文章,前面我已经给了链接。
end
感谢大家的阅读,希望对你们有帮助