优先级队列的详细可以参考官方文档:cplusplus.com/reference/queue/priority_queue/
一. priority_queue的介绍与使用
1.优先级对列是一种容器适配器,它根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
2.优先级队列的底层类似于堆,可以随时插入元素,并且只能位于优先级队列顶部的元素。
3.优先级队列被实现为容器适配器,这个容器适配器使用特定的容器类作为其底层的容器类,并且提供一系列的成员函数来访问其元素。
4.常用成员函数
empty():检测容器是否为空
size():返回容器中有效元素个数
front():返回容器中第一个元素的引用
push_back():在容器尾部插入元素
pop_back():删除容器尾部元素
5.标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指 定容器类,则使用vector。
6. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数 make_heap、push_heap和pop_heap来自动完成此操作。
二. priority_queue的使用
优先级队列默认使用vector作为底层容器,在vector的基础上使用了堆算法,所以优先级队列就是堆,有用到堆的地方都可以考虑优先级队列。优先级队列默认是大堆。
#include<iostream>
using namespace std;
#include <vector>
#include <queue>
#include <functional> // greater算法的头文件
void TestPriorityQueue()
{
vector<int> v{ 3,2,7,6,0,4,1,9,8,5 };
priority_queue<int> q1;//默认是大堆,第三个模板参数为less
// 如果要创建小堆,将第三个模板参数换成greater比较方式
priority_queue<int, vector<int>, greater<int>> q2(v.begin(), v.end());
}
注意:如果要在优先级队列使用自定义类型的数据,用户需要自定义类型中提供>或<的重载。
三.priority_queue的模拟实现
#pragma once
#include<vector>
namespace crin
{
template<class T>
class less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
class greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T, class container = vector<T>, class compare = less<T>>
class priority_queue
{
public:
priority_queue()
{}
template<class InputIterator>
priority_queue(InputIterator begin, InputIterator end)
:_con(begin,end)
{
for (int i = (_con.size() - 2) / 2; i >= 0; i--)
{
adjust_down(i);
}
}
compare com;
void adjust_up(int child)
{
size_t 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;
}
}
}
void adjust_down(int parent)
{
size_t child = parent * 2 + 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[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void pop()
{
swap(_con[0], _con[size() - 1]);
_con.pop_back();
adjust_down(0);
}
bool empty() const
{
return _con.empty();
}
size_t size() const
{
return _con.size();
}
T& top() const
{
return _con[0];
}
private:
container _con;
};
}