求助:解析STL比较器仿函数返回值的含义
我太懂这种对着比较器反复试错的无奈了!之前我也纠结了好久,为啥同样的a<b返回true,在sort里是升序,到priority_queue里好像逻辑就反过来了?咱们就拿你的例子拆解清楚。
先解决你的核心疑问:返回true到底代表什么?
你的问题是:operator()(int a, int b)返回true,是不是意味着a会被置于b之前?
答案是:这完全取决于你用的容器类型! 不同STL容器对比较器的逻辑定义天差地别,这也是最容易踩坑的地方。
1. 排序类场景(比如sort、set、vector+sort)
在std::sort或者std::set这类需要确定线性排列顺序的场景里,comp(a,b)返回true的含义非常直观:a应该被排列在b的前面(也就是a的排序优先级比b高)。比如你写sort(v.begin(), v.end(), [](int a,int b){return a<b;}),得到的就是升序排列,因为小的数会排在前面。
2. priority_queue(优先队列/堆)
重点来了!priority_queue的比较器逻辑完全是另一个路子——它判断的是优先级高低:当comp(a,b)返回true时,说明a的优先级低于b,所以b会被放在更靠近堆顶的位置。换句话说,comp(a,b)返回true,就是在告诉优先队列:“a别抢位置,b比你更该在上面”。
回到你的代码:
struct functor { bool operator()(int a,int b) { return a < b; } }; std::priority_queue<int, std::vector<int>,functor> q;
这个functor和STL自带的std::less<int>逻辑完全一致(std::less<int>本身就是返回a<b),而priority_queue默认用的就是std::less<int>,所以你的这个队列其实是个大顶堆——堆顶会是你push的所有元素里最大的那个(也就是9)。
你之所以觉得自己的理解有误,大概率是误以为返回a<b会让小的数排在堆顶,但实际结果却是大的数在最前面,这就是因为你混淆了排序容器和优先队列的比较器逻辑。
给你一个好记的小技巧
- 排序类场景:
comp(a,b)返回true → a在b前面(要升序就写a<b,要降序就写a>b) - priority_queue:
comp(a,b)返回true → b比a更优先(想要小顶堆?那就写a>b,或者直接用std::greater<int>)
比如你想让堆顶是最小的元素0,只需要把functor改成这样:
struct functor { bool operator()(int a,int b) { return a > b; // 此时a>b返回true,说明a优先级比b低,更小的b会被放在堆顶 } };
再验证下你的例子
当你把{1,8,5,6,3,4,0,9,7,2}push到用你原来functor的priority_queue里,堆顶是9,每次pop都会取出当前最大的元素,最终弹出顺序是9→8→7→6→5→4→3→2→1→0,完全符合大顶堆的逻辑。
内容的提问来源于stack exchange,提问作者MistyD

