首先看一段代码:
#include <queue> #include <deque> #include <iostream> int main() { struct node { int value; }; struct cmp { bool operator()( const node& a, const node& b ) { return a.value < b.value; } }; std::priority_queue<node, std::deque<node>, cmp > pri_queue; node n1 = {22}; node n2 = {11}; node n3 = {33}; node n4 = {11}; pri_queue.push( n1); pri_queue.push( n2); pri_queue.push( n3); pri_queue.push( n4); while( ! pri_queue.empty() ) { node n = pri_queue.top(); pri_queue.pop(); std::cout << n.value << std::endl; } system( "PAUSE"); return 0; };
结果输出 最大值优先的 列表:
但如果将 比较器改成:
struct cmp { bool operator()( const node& a, const node& b ) { return a.value <= b.value; } }; 或者 struct cmp { bool operator()( const node& a, const node& b ) { return true; } };
都会运行异常(当前是 debug 版本):
出现 invalid operator <
原因在于 最后两种的比较器 结果为 true 时是不对称的, 即 如果 A < B 那么对称的应该是 B < A; 即如果 cmp( A, B) 返回true, 那么应该 cmp( B, A) 返回 false, 但不应该
cmp( A, B) = true
cmp( B, A) = true
出现 invalid operator <, 是因为 std::priority_queue 默认使用 less 比较, 如果 A 小于 B 为真, 那么 B 小于 A 就不应该为真,
这里考察
node n2 = {11}; node n4 = {11};
当 调用 push( n4) 时, 必然的要进行排序, 已实现 priority_queue 机制,
检查第一个 cmp 比较器:
struct cmp { bool operator()( const node& a, const node& b ) { return a.value < b.value; } };
cmp( n2, n4 ) = false;
cmp( n4, n2 ) = false;
不会同时为 true , 满足 "结果为true 对称" 条件, 因为这里两个值都为 false.
第二个比较器:
struct cmp { bool operator()( const node& a, const node& b ) { return a.value <= b.value; } };
cmp( n2, n4 ) = true;
cmp( n4, n2 ) = true;
同时为 true了, 不对称, 所以在debug版本运行是报错.
第三个比较器 就更加 不对称了:
struct cmp { bool operator()( const node& a, const node& b ) { return true } };
cmp( n2, n4 ) = true;
cmp( n4, n2 ) = true;
其实我并没有查看过 std::priority_queue的 排序源码, 只是综合其他开发人员的意见有: 当比较器struct cmp 进行比较获取 true 值时, 预期为获取到理想值(较大者?较小者), 再进行后续操作, 但是在 debug 版本时, 会同时检测 两个 比较元素的 不同 lhs 和 rhs 顺序会不会同时为 true, 是的运行报错, 但这是基于什么严格的 设计理念, 我暂时还未能了解到.
本篇总结为, 在设计 比较器时, 要确保 两个元素 n2 和 n4 的 lhs / rhs 顺序 不会同时 为 true.