在c++++中使用priority_queue时,若需自定义优先级排序,主要有两种方法:传入比较函数(或仿函数)和重载运算符。1. 使用仿函数方式更灵活,适合不同优先队列需要不同比较逻辑的场景,例如定义一个compare结构体重载operator()来实现小顶堆或根据结构体成员排序;2. 重载运算符则适合类本身具有自然排序的场景,写法简洁且可读性强,但不便于支持多种排序方式。实际开发中应根据需求选择:需要多种排序方式时用仿函数,类有自然排序时重载运算符,希望代码直观时两者皆可。

在 C++ 中使用
priority_queue时,默认是按照数值大小来决定优先级的,但很多时候我们需要根据自定义类型或者不同的比较规则来调整优先顺序。这时候就需要我们自己定义比较方式,常见做法有两种:传入比较函数(或仿函数) 和 重载运算符。

下面我们就来看怎么实现这两种方法,以及它们分别适合什么场景。

使用比较函数或仿函数定义优先级
当你想让
priority_queue按照某种特定规则排序,而不是默认的
<或
>运算符时,可以传入一个比较函数或仿函数(function object)。
struct Compare {
bool operator()(int a, int b) {
return a > b; // 小顶堆
}
};
std::priority_queue, Compare> pq; 在这个例子中,我们通过仿函数
Compare实现了一个小根堆(最小值先出队),因为默认是大根堆。

如果你用的是结构体或类,也可以这样写:
struct Node {
int val;
};
struct CompareNode {
bool operator()(const Node& a, const Node& b) {
return a.val > b.val; // 按 val 升序排列
}
};
std::priority_queue, CompareNode> pq; 这种方式的好处是:
- 灵活,可以在不同优先队列中使用不同的比较逻辑;
- 不影响原类型的运算符定义;
- 更清晰地表达意图,特别是当比较逻辑复杂时。
重载 <
或 >
运算符的方式
如果你希望某个类的对象可以直接用于
priority_queue而不需要每次都传比较器,那就可以考虑重载它的
<或
>运算符。
比如:
struct Node {
int val;
bool operator<(const Node& other) const {
return val < other.val; // 默认大顶堆
}
};
std::priority_queue pq; 这里重载了
<,所以默认优先队列会按
val从大到小排序。
如果你想改成小顶堆呢?就不能只靠重载
<,而是得配合前面提到的仿函数一起用了,因为默认优先队列依赖
<判断顺序。
这种方式的优点是:
- 写法简洁,适合一个类只有一种常用优先顺序;
- 可读性强,一看就知道这个类型自带排序逻辑;
缺点是:
- 如果一个类需要多种排序方式,就得写多个比较器,不太方便;
- 修改了类的行为,可能影响其他使用该类的地方;
实际选择建议
你可以根据具体情况选择哪种方式更合适:
- ✅ 需要多种排序方式? → 用仿函数传入比较器。
- ✅ 类本身就应有自然排序? → 重载
<
。 - ✅ 希望代码更直观、可读性更高? → 两者都可以,看哪个更清晰。
举个例子:
你有一个任务调度系统,每个任务有个优先级和执行时间。你想按优先级排一次,又想按执行时间排一次,那显然应该写两个仿函数。
而如果你只是处理分数排名,学生类天生就应该按分数比大小,那就直接重载
<更合适。
基本上就这些。两种方式各有优劣,实际开发中灵活选用即可。










