set(集合)
set容器用来存储唯一元素,并且这些元素按照一定的规则排序。在一个集合里面,每个元素同时也是自身的关键字,与map相比,set的key与value是同一个值,所以每个元素必须是唯一的。同时,一旦某个元素插入到容器内,则不能修改其中任何元素,类比map,在map中也不能修改key。但set容器可以插入与删除。
set作为关联容器,与map一样,其内部数据结构为红黑树。
关于set与map这里提几个问题
- 为何map和set的插入与删除效率比用其它容器要高
- 为何每次insert之后,以前保存的iterator不会失效
当数据元素增多时候(10000到20000),map和set的插入和搜索速度变化如何
- 对于第一个问题,只要清楚关联容器内部数据结构便知道为何,对于关联容器,容器内部所有元素都以结点的方式来存储,结点结构和链表差不多。红黑树也是树形结构,因此在插入、删除时都只是添加或删除结点,而其它序列容器在插入或者删除时均需要内存拷贝、移动内存内数据。
- 第二个问题,同样是理解内部数据结构,对于树形结构,iterator相当于指向结点的指针,插入结点后,之前的iterator仍然指向原来的结点。
- 仍然还是依据内部数据结构,红黑树的查找过程类似于二分查找,查找过程的时间复杂度是
$O(logN)$
,也就是说10000个结点,查找最多比较14次,数据增加一倍,比较次数只是多一次,相比序列容器的顺序查找,效率高了很多。
构造函数
std::set<int> first; // empty set of ints
int myints[]= {10,20,30,40,50};
std::set<int> second (myints,myints+5); // range
std::set<int> third (second); // a copy of second
std::set<int> fourth (second.begin(), second.end()); // iterator ctor.
迭代器
- 与其他容器一样,可以使用迭代器
set<int> first = {1, 2, 3, 4};
set<int>::iterator it;
for (it = first.begin(); it != first.end(); it++)
{
cout << *it << endl;
}
容器容量
set<int> first = {1, 2, 3, 4};
cout << first.size() << endl;
cout << first.empty() << endl;
容器修改
//插入
//插入函数的返回值是一个pair,pair里面第一个值为迭代器,第二个值为是否插入成功,如果插入的值已经在关键字中,则插入失败。
std::set<int> myset;
std::set<int>::iterator it;
std::pair<std::set<int>::iterator,bool> ret;
// set some initial values:
for (int i=1; i<=5; ++i) myset.insert(i*10); // set: 10 20 30 40 50
ret = myset.insert(20);
if (ret.second == false)
{
it = ret.first;
}
myset.insert(it, 25);
int myints[]= {5,10,15};
myset.insert(myints, myints+3);
//前面知道,关联容器内部数据结构为红黑树,树形结构在插入时,需要找到正确的插入位置,因此上面这种先查找,查找失败,但迭代器指向了比较近的结点位置,因此再次插入时,则需要查找的次数就会比较少。如果不提供插入迭代器,则会从树根开始查找,时间效率较低。
//删除
int n = first.erase(20); //返回被删除元素个数,set里面只会是1或者0
first.swap(myset); //两个set互换
first.clear(); //集合清空
it = first.find(20); //查找,返回迭代器,未查找到则返回first.end()
first.count(20); //类似于find,如果查找到则返回1,未查找到返回0
后记
set可以看成是key/value相同的map,在实际使用中,能够set的地方都可以用map进行替换,关联式容器每次插入元素都会自动排序,因此要获取元素只能通过关键字,而不能通过绝对的索引(如序列式容器vector,list,string等)。而且一旦元素插入后,只要没有删除操作,元素位置不会改变,因此即便是插入元素,之前的iterator仍然可以使用。