大家好,我是梁唐。今天继续聊聊C++中的set。上篇文章有个问题没有解答,有小伙伴有些疑惑。所以说set是关联容器,这个关联体现在哪里。其实很简单。我们说过集合内部使用红黑树对所有元素进行排序。在树结构中,我们通常使用的形式。key是用来排序的,value就是我们实际存储的值。只是set有点特殊,它的value和key是一样的,相当于的形式,所以还是一个关联容器。今天这篇文章主要讲一下set的API和一些特殊的用法。创建集合从集合容器的类模板定义开始。template,//指定set容器内部的排序规则classAlloc=allocator//指定allocator对象的类型>classset;第一个参数表示集合中元素的类型,第二个参数是集合容器内部的排序规则,第三个参数可以忽略,一般不用。set的构造函数有3种,分别适用于不同的场景。让我们简要地列出它们。第一种类型setst;最常规的,没有任何参数,直接创建。第二种setst{"good","bad","medium"};直接枚举我们要通过花括号传入集合中的值。第三组st{"good","bad","medium"};setst2(st);复制创作,从另一组复制元素。除了这三种形式的构造函数之外,还可以通过set类模板的第二个参数传入元素排序规则来影响set中元素的排序。这勉强是一种构造方法:set>st{"good","bad","medium"};我们不传入greater的排序结果是“bad”,“good”,“medium”,当我们传入这个参数时,结果会变成:“medium”,“good”,“bad”。这是因为我们传入的排序规则重新定义了元素的大小关系。使用集合创建集合后,需要使用,使用无非就是增删改查。先说增量。向集合中添加元素的函数有几个,下面一一说。insert插入函数很简单,直接调用,插入集合即可。st.insert("hhh");但是insert也可以批量插入多个元素:st.insert({"hhh","wow"});emplaceemplace函数与insert功能相同,可以向集合中插入元素。它和insert最大的不同在于emplace传递的参数不是要插入的元素,而是构造元素所需要的参数。这个我说起来可能有点难,其实很简单,我们来对比一下。假设我们有一个类型为结构P的集合,并且我们重载了它的比较运算符,现在将忽略它。structP{intx,y;P(intx,inty):x(x),y(y){};booloperator<(constPb)const{returnthis->xst;如果我们如何使用插入?Pp{0,3};st.insert(p);如果使用emplace函数,是这样的:st.emplace(1,23);因为emplace内部会帮我们调用结构体P的构造函数,使用1和23这两个参数构造一个P的实例存储在集合中。使用emplace可以省去创建实例的步骤,所以emplace在项目中经常被大量使用。emplace函数返回的结果是一对。pair的第一个元素是集合的迭代器,表示插入元素的位置,第二个值为bool,表示插入是否成功。emplace_hintemplace函数的改进版本,它接受一个附加参数,指示在何处插入集合。它的返回结果也发生了一些变化,返回了一个迭代器。如果插入成功,则返回新添加的元素,否则指向set容器中与添加元素相同的元素。使用emplace_hint会影响集合中的顺序,所以一般不推荐使用。擦除说完插入,再说说删除。set中删除的方法只有一种,就是erase,但是它有多种用法。我们直接看它的函数签名:size_typeerase(constvalue_type&val);迭代器擦除(const_iteratorposition);迭代器擦除(const_iteratorfirst,const_iteratorlast);在第一个方法中,我们传入了一个val值,也就是我们要删除的元素。我们传入的第二个方法是一个迭代器,它删除迭代器指向的元素。第三种方法类似,只是我们传入了两个迭代器,代表一个范围,它会删除这个范围内的所有元素。第一个方法的返回值是一个整数,表示删除元素的数量。后两者返回一个迭代器,指向被删除元素后面的位置。clear清除集合。findset中的query函数传入我们要查询的值,返回一个迭代器。set::iteratorit=st.find("good");如果成功找到,返回指向元素的迭代器,否则指向结束。count也是一个查询函数,只不过它返回的不再是一个迭代器,而是一个整数,表示在查询中找到的元素个数。intcnt=st.count("好");lower_bound和upper_boundlower_bound和upper_bound也是严格意义上的查询函数,只是它们查询的范围。lower_bound查询是集合中第一个大于等于val的位置,upper_bound查询是集合中第一个严格大于val的位置。set::iteratorit_low=st.lower_bound("i");set::iteratorit_up=st.upper_bound("i");这两个函数也返回一个迭代器。equal_range函数返回一对,其第一个元素是lower_bound的结果,第二个元素是upper_bound的结果。pair::iterator,set::iterator>ret=st.equal_range("i");综上所述,set常用的方法基本介绍完了。还有其他一些琐碎的方法,我就不赘述了。比如像size()、max_size()等,可以用它来查询。但是有一个问题不知道大家有没有发现,就是我们没有引入修改函数。难道set不支持修改?回答这个问题,不是老梁要刁钻,而是很复杂,很难一两句话说清楚。老梁将在下一篇文章中讨论这个问题。如果需要修改元素,可以改用erase+insert。本文转载自微信公众号“码农”,可通过以下二维码关注。转载本文请联系编码员梁公众号。