C++中priority_queue比较器是否与普通比较器逻辑相反?
核心原因非常直接:两个STL组件对比较器返回值的语义定义完全不同,哪怕比较逻辑的代码写得一模一样,最终呈现的顺序也会相反。
std::sort的比较器规则
std::sort的比较器遵循严格弱序约定:当comp(a, b)返回true时,代表参数a应该排在参数b的前面。排序完成后的序列满足:任意位置靠前的元素,和它后面的元素同时传入比较器时,返回值都为true。
你实现的compare函数返回a < b,判定更小的数应该排在更靠前的位置,所以最终vector排序结果是1, 7, 20的升序,完全符合逻辑。
std::priority_queue的比较器规则
std::priority_queue是基于堆结构实现的优先级适配器,它的比较器语义和sort完全不一样:当comp(a, b)返回true时,代表参数a的优先级低于参数b,b会被放在更靠近堆顶的位置,a会被下沉到堆的下层。最终top()接口返回的,是所有元素中、和其他任意元素比较都不会让comp返回true的那个——也就是优先级最高的元素。
你实现的cmp结构体逻辑,和C++标准库给priority_queue默认配置的std::less<int>完全一致:当a < b时返回true,也就是判定更小的数优先级更低,更大的数优先级更高,最终生成的是大顶堆,堆顶永远是当前容器内最大的元素,所以依次出队的顺序是20, 7, 1的降序。
注意:priority_queue的比较器会直接传给底层的堆操作函数(
make_heap/push_heap/pop_heap),这类堆函数的比较器语义本身就和sort不同:用std::less会生成大顶堆,用std::greater才会生成小顶堆,不要直接套用sort的比较器使用经验。
让两者输出顺序一致的方法
如果要让priority_queue的出队顺序和sort的升序结果保持一致(从小到大输出),只需要把priority_queue的比较器逻辑反过来,返回a > b(等价于直接使用std::greater<int>作为比较器),就能得到小顶堆,出队顺序就会和sort的升序结果完全相同。
内容的提问来源于stack exchange,提问作者Mann Jain

