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
STL注意比较函数的更多相关文章
- STL传递比较函数进容器的三种方式
对于STL中的依靠比较排序的容器,均提供了一个模板参数来传递比较函数,默认的为std::less<>. 查阅Containers - C++ Reference可以看到典型的使用比较函数的 ...
- 对于一些stl自定义比较函数
1.unorderd_map自定义键 自定义类型 struct my_key { int num; string name; }; 1.由于unordered_map是采用哈希实现的,对于系统的类型i ...
- 各种注意事项(还有c++的一些操作)
转c++时间: 2017年8月9号 1.记得打头文件 2.=与==的区别(赋值|比较) 3.各种运算符的比较级(与Pascal不同),主要是==与位运算 *4.在OJ上scanf和printf时间优于 ...
- STL中sort、priority_queue、map、set的自定义比较函数
STL中,sort的默认排序为less,也就是说从小到大排序:priority_queue默认是less,也就说大顶堆:map默认是less,也就说用迭代器迭代的时候默认是小的排在前面:set默认是l ...
- 详细解说 STL 排序(Sort)
0 前言: STL,为什么你必须掌握 对于程序员来说,数据结构是必修的一门课.从查找到排序,从链表到二叉树,几乎所有的算法和原理都需要理解,理解不了也要死记硬背下来.幸运的是这些理论都已经比较成熟,算 ...
- C++ STL简述
前言 最近要找工作,免不得要有一番笔试,今年好像突然就都流行在线笔试了,真是搞的我一塌糊涂.有的公司呢,不支持Python,Java我也不会,C有些数据结构又有些复杂,所以是时候把STL再看一遍了-不 ...
- STL sort 函数实现详解
作者:fengcc 原创作品 转载请注明出处 前几天阿里电话一面,被问到STL中sort函数的实现.以前没有仔细探究过,听人说是快速排序,于是回答说用快速排序实现的,但听电话另一端面试官的声音,感觉不 ...
- STL~heap
1.定义 堆:若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树 树中任一非叶子结点的关键字均不大于(或不小于)其子结点的关键字.分为大根数(默认 ...
- STL set 用法
c++ stl集合set介绍 c++ stl集合(Set)是一种包含已排序对象的关联容器.set/multiset会根据待定的排序准则,自动将元素排序.两者不同在于前者不允许元素重复,而后者允许. ...
随机推荐
- Linux学习--进程概念
>>进程 说进程,感觉好空洞,来一张图,Linux下的进程: ps -eo pid,comm,cmd 说明:-e表示列出全部进程,-o pid,comm,cmd表示我们需要PID,COMM ...
- JAVA线程池原理详解(1)
线程池的优点 1.线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用. 2.可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃. 线 ...
- socket , 套接口还是套接字,傻傻分不清楚
socket 做网络通信的朋友大都对socket这个词不会感到陌生,但是它的中文翻译是叫套接口还是套接字呢,未必大多数朋友能够分清,今天我们就来聊聊socket的中文名称. socket一词的起源 在 ...
- 开发者的如何优雅的使用OSX
Mac对于IT开发者来说是最好的开发工具,没有之一. 但是对于大部分人来说,第一个接触的PC操作系统都是Windows系统,此文将带大家优雅的快速学习和使用Mac的OSX系统. 1. 从键盘说起 Ma ...
- CentOS搭建Git服务器及权限管理
声明:本教程,仅作为配置的记录,细节不展开,需要您有一点linux的命令基础,仅作为配置参考. 1. 系统环境 系统: Linux:CentOS 7.2 64位 由于CentOS已经内置了OpenSS ...
- linux系统命令学习系列-用户切换命令su,sudo
先复习一下上节内容: 用户组添加groupadd 用户组修改groupmod 用户组删除groupdel 作业创建一个id为501的组group1,然后改成group2, 同时id变为502,最后删除 ...
- Java基础类库简介
Java基础类库简介 一.常用的基础类库:11个jar(Java Archive,Java归档)包 作为java语言使用者,我们可以感受到java语言带来的优势(平台无关.面向对象.多线程.高效易扩展 ...
- Lock(三)查看是谁把表给锁了
查看是谁把表给锁了 select se1.inst_id as 被阻塞的会话节点, se2.inst_id as 罪魁祸首节点, se1.sid as 被阻塞的会话ID, ob.object_name ...
- c# aynsc 和 await
static void Main(string[] args) { Print(); Console.WriteLine("这是主线程"); } public static a ...
- node.js的安装的配置
一.Node.js 安装配置 Node.js 提供在Windows和Linux上安装 1. Window 上安装Node.js 64 位安装包下载地址 : https://nodejs.org/di ...