zoukankan      html  css  js  c++  java
  • STL注意比较函数

    可重复插入?:

    set<int ,less_equal<int> >s;
    s.insert(10);
    s.insert(10);
    

    第二次调用insert,集合回去确认10是否已经存在。因为我们代入的比较函数是 <=
    所以集合会检查下面表达式判断是否等价:

    !(10a <= 10b) && !(10b <= 10a)
    

    于是会判断出不等价,第二个10就插入成功了。。
    至于为什么是这个公式,具体可以参考《STL源码剖析里面》的RB-tree代码:
    因为在插入的时候会调用 RB-tree的insert_unique(即避免重复)。然后做出一下判断:

    • 插入点是父亲是最左节点的左儿子:那么直接插入
    • 插入点是普通的左儿子:判断与插入点的祖父点是否相等
    • 插入点是右儿子:直接判断与父亲的关系

    假设判断函数‘<’:

    • 最左节点就是值最小的那个点,如果插入点是它左儿子,那么肯定不可能与它相同
    • 如果你是普通左儿子,那么肯定小于父亲节点,而父亲节点 >= 祖父节点,所有当前值有可能与祖父值相同。
    • 如果是右儿子,那么>=父亲节点
    • 对于可能相等的情况判断一下
      于是会先判断 (10b < 10a),因为相等,所以插在右儿子,然后它判断与父亲点的关系
      也就是 (10b > 10a)。如果两个都满足的话,两个点是不相同的。

    --
    但是判断函数换成了 less_equal( <= ),那么就会有一定的问题,导致相同的也能够插入成功。


    元素是指针:

    set<string* > v;
    v.insert(new string("abc"));
    v.insert(new string("bcd"));
    

    如果按照上面的操作,然后将内容按顺序输出,你希望的:
    abc bcd
    并不一定会出现,因为默认比较函数是比较元素,而set里面保存的是指针。
    最后输出的是按照指针大小排序后的结果,所以需要一些处理:

    struct StringPtrLess:
      public binary_function<const string*,const string*,bool>
      {
        bool operator()(const string *p1,const string* p2) const 
        {
             return *p1 < *p2;
        }
      };
    

    自定义比较,然后代入set的声明中

    而且因为自定义的比较,可能导致成员函数的find和算法的find出现不同结果。


    参考:

    Effective STL

  • 相关阅读:
    dubbo 在不同协议下携带上下文区别
    innodb使用大字段text,blob的一些优化建议(转)
    Redis的过期策略和内存淘汰策略(转)
    在 Docker 里跑 Java,你必须知道的那些事儿!(转)
    如何在宿主机上执行容器里的jmap,jtack,jstat 命令获取信息(原创)
    操作系统实现线程的几种模式 和 java创建线程的3个方式
    MySQL数据库事务各隔离级别加锁情况--read committed && MVCC
    kafka性能调优(转)
    游戏数值系统
    lua函数回调技巧
  • 原文地址:https://www.cnblogs.com/Przz/p/6591019.html
Copyright © 2011-2022 走看看