zoukankan      html  css  js  c++  java
  • 排序仿函数 出现 std::priority_queue::push() 的 invalid operator < 异常

    首先看一段代码:

    #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.

  • 相关阅读:
    cef加载flash的办法
    一个高性能的对象属性复制类,支持不同类型对象间复制,支持Nullable<T>类型属性
    php检测php.ini是否配制正确
    openwrt的路由器重置root密码
    windows 7 + vs2010 sp1编译 x64位版qt4
    解决SourceGrid在某些系统上无法用鼠标滚轮滚动的问题
    判断一个点是否在多边形内部,射线法思路,C#实现
    [转载]使用HttpWebRequest进行请求时发生错误:基础连接已关闭,发送时发生错误处理
    让Dapper+SqlCE支持ntext数据类型和超过4000字符的存储
    通过WMI
  • 原文地址:https://www.cnblogs.com/Wilson-Loo/p/3375325.html
Copyright © 2011-2022 走看看