std::priority_queue默认是大顶堆,因其第三个模板参数compare默认为std::less,它使较小元素优先级更高;改为小顶堆需显式传入std::greater或自定义仿函数,且要求类型支持operator>或在仿函数中正确实现a>b表示a优先级更低。

默认情况下 std::priority_queue 是大顶堆,要变成小顶堆,必须显式替换比较器模板参数,不能只靠 std::greater<int></int> 就完事——它只是其中一种可行方式,且有前提条件。
为什么默认不是小顶堆?
std::priority_queue 的第三个模板参数是 Compare,类型为 bool( const T&, const T& ) 的可调用对象,默认是 std::less<t></t>。而 std::less 返回 a ,导致“更大的元素优先出队”,即大顶堆。
小顶堆要求“更小的元素优先出队”,所以比较器逻辑应让 a > b 时返回 true(即:当 a 应该排在 b 后面时,认为 a “优先级更低”)。
正确写法:用 std::greater 或自定义仿函数
最常用且安全的方式是传入 std::greater<t></t>,但它要求 T 支持 operator>;若自定义类型未重载 >,则编译失败。
立即学习“C++免费学习笔记(深入)”;
- 对内置类型(如
int,double)直接可用:std::priority_queue<int, std::vector<int>, std::greater<int>> min_heap;
- 对自定义结构体,需提供
operator>或用 lambda(C++20 起支持,但需配合std::priority_queue的容器适配限制);更稳妥的是写仿函数:struct Compare { bool operator()(const MyStruct& a, const MyStruct& b) { return a.value > b.value; // 注意:这里 a > b 表示 a 优先级更低 } }; std::priority_queue<MyStruct, std::vector<MyStruct>, Compare> min_heap;
常见错误:误用 std::less 或反向写比较逻辑
以下写法都是错的:
- 写成
std::less<int></int>:仍是大顶堆 - 写成
std::greater<int></int>但忘了指定容器类型(第二个模板参数):默认是std::vector<int></int>,但若手动写了其他容器(如std::deque),必须显式写出全部三个参数 - 自定义比较器里写
return a.value :这反而实现的是大顶堆逻辑 - 以为用
std::priority_queue的top()取最小值就等于小顶堆——其实只是碰巧当前 top 是最小,内部结构仍是大顶堆,pop 后行为不可预期
性能与底层容器的影响
std::priority_queue 是适配器,底层默认用 std::vector,所有操作时间复杂度不变(push/pop 是 O(log n))。但若换成 std::deque,虽合法,却可能因缓存不友好略微变慢;std::list 则完全不可用——它不支持随机访问,无法建堆。
真正容易被忽略的是:比较器类型必须满足严格弱序(strict weak ordering),否则行为未定义。比如用 != 或 实现比较器,会导致 <code>push 崩溃或死循环。







