set类型容器
set容器只是单纯的键的集合,其中的键必须唯一,且不能修改(const)。
举个例子:
某软件提供黑名单功能,其黑名单就可用set容器配置。在做某项操作前,先检查黑名单。
set支持大部分map的操作,有两点例外:
1、set不支持下标操作,且没有定义mapped_type。
2、set中,value_type不是pair类型,而是与key_type相同的类型。
因为只是单纯的键集合,没有关联的值。
添加元素操作
1、s.insert(v):在s中添加值为v的元素。返回一个pair类型,其组成包括一个指向新添加元素的迭代器,和一个是否成功添加元素的bool值。
2、s.insert(iter1,iter2):在s中添加iter1和iter2所组成的范围内的元素。如范围内存在重复的元素,则只添加一次。返回void。
获取元素操作
1、s.find(v):在s中搜索值为v的元素。如搜索到,则返回指向被搜索元素的迭代器。否则,返回指向超出容器末端的下一位置的迭代器。
2、s.count(v):统计s中搜索值为v的元素的个数。返回值为为元素的个数。对于set来说,返回值只有可能是0或1。
multimap和multiset
map和set中,一个键只能对应一个值(键唯一)。而在multimap和multiset中,允许一个键出现多次,也就形成了一键对应多值的结构。
例如,在电话号码本应用中,一个人(键)可能有多个电话号码(值)。
multimap和multiset使用之前必须包含头文件:
#include <map>
#include <set>
multimap和multiset所支持的操作,于map和set操作相同。只有一个例外:multimap不支持下标操作,这也是合理的,因为某个键可能对应多个值。
添加与删除元素
可直接调用insert和erase操作,基于一键对多值的结构,会有一些变化,考虑下面的例子:
multimap<string,int> si_mmap;
si_mmap.insert(make_pair(string("haha"),1));
si_mmap.insert(make_pair(string("haha"),2));
由于键不要求唯一,则每次调用insert总会添加一个元素。以上的例子,对于haha键来说,有两个值,1和2。
对应的,参数为一个键的删除操作,会删除拥有该键的所有元素,考虑以下的例子:
multimap<string,int>::size_type cnt;
cnt=si_mmap.erase("haha");
这将返回被删除元素的个数。在本例中,cnt的值为2。
当然也会有参数为一个或一对迭代器的版本,对于这个版本,只删除被指向的元素(或范围内的元素)。
查找元素
map和set中的元素是顺序存储的,而multimap和multiset也一样。因此,如果在容器中某个键对应多个值,则这些值是相邻着存放的。这也就意味着,在用迭代器遍历容器时,会依次返回特定键关联的所有元素。
在map和set中查找一个元素很容易,要么在,要么不在。而在multimap和multiset中,就比较复杂,因为一键可能对应多值。
为了解决这一问题。有三种可行的方案。
1、使用find和count。考虑以下的例子:
string search_item("haha");
typedef multimap<string,int>::size_type sz_type;
sz_type num=si_mmap.count(search_item);//获取容器中,键为search_item的元素的个数
multimap<string,int>::iterator iter=si_mmap.find(search_item);//获取指向第一个键为search_item的元素的迭代器
for(sz_type cnt=0;cnt!=num;++cnt,++iter)
cout <<iter->second <<endl;
以上的例子中,关键的一点在于,如果在容器中某个键对应多个值,则这些值是相邻着存放的。
2、使用lower_bound和upper_bound函数
这是两个关联容器的操作
lower_bound参数为一个键,返回一个迭代器,指向键不小于k的第一个元素。
upper_bound参数为一个键,返回一个迭代器,指向键大于k的第一个元素。
如使用同一个键调用以上两个函数,则返回了一个迭代器范围,这个范围恰好就是指定的键对应的所有值的范围。
我们用这两个函数重写上面的例子:
typedef multimap<string,int>::iterator mm_iter;
//以下两个操作获取迭代器对
mm_iter beg=si_mmap.lower_bound(search_item);
mm_iter end=si_mmap.upper_bound(search_item);
while(beg!=end)
{
cout <<beg->second <<endl;
++beg;
}
3、使用equal_range函数
这个函数使用一个键作为参数,返回一个pair类型,由lower_bound和upper_bound的返回值组成。
由以上的定义,我们可以写出更简洁的代码,重写以上的例子:
pair<mm_iter,mm_iter> pos=si_mmap.equal_range(search_item);
while(pos.first!=pos.second)
{
cout <<pos.first->second <<endl;
++pos.first;
}