一、优先级队列的定义
在文档中,是这样定义优先级队列的
1、优先级队列是一钟容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的;
2、优先级队列类似于堆,在堆 中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素);
3、优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为底层容器类,queue提供一组特定的成员函数来访问其元素,元素从特定元素的尾部弹出,其称为优先 队列的顶部;
4、底层容器可以时任何标准容器类模版,也可以是其他特定设计的容器类,容器应该可以通过随机访问迭代器访问,并支持以下操作:
empty() :检测容器是否为空;
size():返回容器中有效元素个数
front():返回容器中第一个元素的引用
push_back():在容器尾部插入元素
pop_back():删除容器尾部元素
5、优先级队列默认使用大堆,默认使用vector作为底层存储数据的容器。
二、priority_queue的使用
1、默认情况下创建的是大堆,底层按照小于比较
int main()
{
priority_queue pq;
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(4);
pq.push(5);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
system("pause");
return 0;
}
输出结果:
2、对于小堆的比较,要借助仿函数,即函数对象
在库里面,优先级队列的定义格式为:
template
less创建的是大堆,要建小堆,只需将less改为greater,并加上头文件 #include functional
int main()
{
priority_queue, greater> pq;
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(4);
pq.push(5);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
system("pause");
return 0;
}
template
struct Greater
{
bool operator()(const T& left, const T& right)
{
return left < right;
}
};
3、如果在priority_queue中放自定义类型的数据,需要在自定义类型中提供<和>的重载,下面以日期类的比较为例说明
由于Date类中存在多个比较对象,无法重载库里面的大于或者小于,所以需要自己定义大于和小于
class Date
{
public:
Date(int year = 2019, int month = 3, int day = 5)
:_year(year)
,_month(month)
,_day(day)
{}
bool operator<(const Date& d) const
{
return (_year < d._year) ||
(_year == d._year && _month < d._month) ||
(_year == d._year && _month == d._month && _day < d._day);
}
private:
int _year;
int _month;
int _day;
};
int main()
{
priority_queue,greater> pq;
pq.push(Date(2018, 10, 1));
pq.push(Date(2019, 3, 1));
pq.push(Date(2018, 1, 1));
pq.push(Date(2019, 3, 6));
Date top = pq.top();
system("pause");
return 0;
}
调试结果:
同理,当使用less时,需要自己重载大于;此处就不再列出代码。
4、有些情况下,需要自己定制比较器规则
例如:比较商品的价格、销量、综合指数等,此时需要为每个成员定义一个仿函数,然后在比较的时候调用各自的仿函数即可。
下面以比较价格为例,用代码加以说明:
class Goods
{
public:
int _price;
int salves_volume;
int _comprehensive;
};
struct GoodsPriceLess
{
bool operator()(const Goods& l1, const Goods& l2)
{
return l1._price > l2._price;
}
};
以上是我对优先级队列的理解,各位大佬若有建议,可在评论区留言!