和vector、list不同,set、map都是关联式容器。set内部是基于红黑树实现的。插入和删除操作效率较高,因为只需要修改相关指针而不用进行数据的移动。
删除set的数据时,实际的操作是删除红黑树中的一个节点,然后相关指针做相关调整。指向其他元素的迭代器还是指向原位置,并没有改变,所以删除一个节点后其他迭代器不会失效。list和map也是同样的道理。
然而删除vector中的某个元素,vector中其他迭代器会失效,因为vector是基于数组的,删除一个元素后,后面的元素会往前移动,所以指向后面元素的迭代器会失效。(插入元素造成内存重新分配的话,所有迭代器都会失效)
再稍微说一下迭代器的实现。迭代器是一个对象,vector的迭代器是封装了数组下标;list、map、set的迭代器是封装了元素节点的指针。
所以set有以下2个特点:
1、search操作效率会很高O(log n)
2、set中元素的值不能直接被改变,但是可以删除某个元素或插入新的元素。
定义:集合(Set)容器是一个按特定顺序存储唯一(Unique)元素的关联容器。
stl中set模板类形式如下:
// <set>
template < class T,
class Compare = less<T>,
class Alloc = allocator<T> >
> class set;
这里的模板参数:
T
元素的类型。
在类模板内部,使用其别名为 key_type 及 value_type 的成员类型。
Compare
一个二元谓词,以两个元素为参数返回一个 bool 值。可以是函数指针(Function pointer)类型或函数对象(Function object)类型。在类模板内部,使用其别名为 key_compare 及 value_compare 的成员类型。
Alloc
容器内部用来管理内存分配及释放的内存分配器的类型。这个参数是可选的,它的默认值是 std::allocator<T>,这个是一个最简单的非值依赖的(Value-independent)内存分配器。在类模板内部,使用其别名为 allocator_type 的成员类型。
set 容器中的所有元素都是按由类型为 Compare 的比较对象指定的严格弱序规则排序的。并且set支持双向迭代。
另外,从模板来看,set在定义的时候可以把自定义的比较函数当参数传入:
struct myComp
{
bool operator()(const your_type &a,const your_type &b)
[
return a.data-b.data>0;
}
}
set<your_type ,myComp> s;
或者set元素是自定义的数据结构时,重载自定义数据类型的比较运算符:
struct Info
{
string name;
float score;
//重载“<”操作符,自定义排序规则
bool operator < (const Info &a) const
{
//按score从大到小排列
return a.score<score;
}
}
set<Info> s;
最后整理归纳了stl中set容器支持的操作:
//set支持的操作:
set<int> myset,myset1;
myset.begin();
myset.end();
myset.rbegin();
myset.rend();
myset.size();
myset.clear();//清空
myset.empty();
myset.max_size();
myset.count(2);//计算2的个数,set只可能是0或者1
myset.insert(2);//插入2
/*insert(key_value); 将key_value插入到set中 ,返回值是pair<set<int>::iterator,bool>,bool标志着插入是否成功,而iterator代表插入的位置,若key_value已经在set中,则iterator表示的key_value在set中的位置。
*/
inset(first,second);//将定位器first到second之间的元素插入到set中,返回值是void.
myset.emplace(2);//构造然后插入
myset.emplace_hint(2,5);//按提示构造及插入一个元素
myset.erase(2);//删除2
//erase(iterator) ,删除定位器iterator指向的值
//erase(first,second),删除定位器first和second之间的值
//erase(key_value),删除键值key_value的值
iterator find (const value_type& val);//在set中查找是使用二分查找,没找到则返回.end()
myset.swap(myset1);