C++优先级队列中的多次比较
优先级队列(Priority Queue)是一个自动排序的容器,在C++ STL中有相关实现,常用于解决优先级问题。默认情况下,C++ STL中的优先级队列是按照元素大小进行比较排序的,但当我们需要对元素进行多次比较时,就需要在定义队列时传入比较函数来实现自定义排序。
默认的比较
首先,让我们看一下默认情况下的优先级队列的比较规则。假设我们定义了一个存储整数的优先级队列:
#include <iostream>
#include <queue>
using namespace std;
int main()
{
priority_queue<int> pq;
pq.push(3);
pq.push(1);
pq.push(4);
pq.push(1);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
return 0;
}
这段代码将输出:4 3 1 1。
我们发现,优先级队列会按照元素大小进行比较,默认的比较规则是该类型的“小于”运算符。在C++ STL中,小于运算符可以通过重载来实现自定义,其定义方式为bool operator< (const 该类型& a, const 该类型& b)
。
自定义比较
但是,当我们需要对元素多次进行比较时,如果只能使用小于运算符,就无法实现,此时我们就需要在定义队列时传入自定义比较函数。
#include <iostream>
#include <queue>
#include <string>
using namespace std;
struct Student
{
string name;
int age;
int score;
};
bool cmp1(const Student& a, const Student& b)
{
return a.age > b.age; // 按照年龄从大到小排序
}
bool cmp2(const Student& a, const Student& b)
{
return a.score < b.score; // 按照分数从小到大排序
}
int main()
{
priority_queue<Student, vector<Student>, decltype(&cmp1)> pq(cmp1); // 按照年龄排序
// priority_queue<Student, vector<Student>, decltype(&cmp2)> pq(cmp2); // 按照分数排序
pq.push(Student{"Lucy", 20, 92});
pq.push(Student{"Alice", 18, 86});
pq.push(Student{"Tom", 22, 80});
pq.push(Student{"Bob", 19, 88});
while (!pq.empty())
{
Student s = pq.top();
cout << s.name << " " << s.age << " " << s.score << endl;
pq.pop();
}
return 0;
}
这段代码定义了一个存储学生信息的优先级队列。在定义队列时,需要传入三个参数:元素类型、底层容器类型和比较函数类型。比较函数类型要使用decltype
来推导。在本例中,分别定义了两个比较函数,一个按照年龄排序,一个按照分数排序。我们可以选择其中一个比较函数来传入队列构造函数,这样就可以实现自定义排序了。
我们可以把第15行代码注释掉,改为第16行代码,这样就可以按照分数排序。运行结果如下所示:
Lucy 20 92
Bob 19 88
Alice 18 86
Tom 22 80
结论
C++ STL中的默认优先级队列是按照元素大小(小于运算符)进行比较的,如果需要自定义比较规则,需要在定义队列时传入自定义比较函数,并在比较函数中编写自己的比较规则。通过传入不同的比较函数,我们可以实现不同的排序需求。