目录
1. priority_queue简单介绍
①在优先队列中,元素被赋予优先级(按约定的函数来赋予优先级,底层通过堆来实现)。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。
②优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆。
③定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。
//升序队列,小顶堆 priority_queue <int,vector<int>,greater<int> > q; //降序队列,大顶堆 priority_queue <int,vector<int>,less<int> >q; //greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
2. priority_queue代码测试
各部分结果见注释:
#include <queue>
#include <list>
#include <functional>
void TestPriorityQueue1()
{
priority_queue<int> q;
q.push(4); //注意是push 不是push_back
q.push(1);
q.push(5);
q.push(3);
q.push(7);
q.push(2);
q.push(6);
cout << q.size() << endl; //7
cout << q.top() << endl; //7
q.pop();
q.pop();
// 注意:堆顶元素不能修改,因为修改之后可能不能满足堆的特性
cout << q.top() << endl; //5
}
void TestPriorityQueue2()
{
list<int> L{4,1,5,3,7,2,6};
priority_queue<int, vector<int>, greater<int>> q(L.begin(), L.end()); //构建的是小根堆
}
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
bool operator<(const Date& d)const
{
if ((_year < d._year) ||
(_year == d._year && _month < d._month) ||
(_year == d._year && _month == d._month && _day < d._day))
{
return true;
}
return false;
}
private:
int _year;
int _month;
int _day;
};
void TestPriorityQueue3()
{
priority_queue<Date> q; //存放的是自定义类型
Date d1(2022, 5, 29);
Date d2(2022, 5, 28);
Date d3(2022, 5, 30);
q.push(d1);
q.push(d2);
q.push(d3); //2022 5 30 2022 5 28 2022 5 29
}
bool LessFunc(const Date* left, const Date* right)
{
return *left < *right; //这里不能改为> 因为Date里没有>运算符重载
}
typedef bool (*LessF)(const Date*, const Date*); //声明LessF为一个类型
//注意<>里必须放的是类型(类似模板) 所以用typedef将LessF看作类型
void TestPriorityQueue4()
{
priority_queue<Date*, vector<Date*>, LessF> q(LessFunc);
Date d1(2022, 5, 29);
Date d2(2022, 5, 28);
Date d3(2022, 5, 30);
q.push(&d1);
q.push(&d2);
q.push(&d3); //2022 5 30 2022 5 28 2022 5 29
}
// 如果想要让一个类的对象按照函数调用的方式进行使用
// 还需在该类中将()即“函数调用运算符”重载即可 ---推荐使用该方法而不是上面的方法
class Less
{
public:
bool operator()(const Date* left, const Date* right)const
{
return *left < *right;
}
};
//推荐用TestPriorityQueue5这种方法,写个类,重载(),然后就可以用Less。
void TestPriorityQueue5()
{
priority_queue<Date*, vector<Date*>, Less> q;
Date d1(2022, 5, 29);
Date d2(2022, 5, 28);
Date d3(2022, 5, 30);
q.push(&d1);
q.push(&d2);
q.push(&d3);
Less lessObj;
lessObj.operator()(&d1, &d2);//也可以写成下面的形式
// lessObj不是函数名,而是Less的一个对象
// lessObj: 函数对象----就是可以像函数调用一样使用的对象
// 也称为仿函数
lessObj(&d1, &d2);
// LessFunc是一个真正的函数
LessFunc(&d1, &d2);
}
int main()
{
//TestPriorityQueue1();
//TestPriorityQueue2();
//TestPriorityQueue3();
//TestPriorityQueue4();
TestPriorityQueue5();
return 0;
}