关联容器的类型:
map:关联数组;元素通过键来从存储读取
set:大小可变的集合,至此后通过建实现快速读取
multimap:支持同一个键多次出现的map类型
multiset:支持同一个键多次出现的set类型
一般来说,如果希望有效地存储不同值的集合,那么使用set比较合适,而map容器则更适用于需要存储乃至修改每个键所干练的值的情况。在做某种文本处理时,可使用set保存要忽略的单词。而字典是map的一种很好的应用,单词本身是键而他的解释说明则是值,
在开始介绍关联容器之前必须先了解一种鱼值相关的简单的标准库类型--pair类型;该类型在utility中定义。
pair的基本操作;
pair<string , string >anon;//
pair<string ,int >word_count;//包含一个空的string和一个空的int
pair<string,vector<int> >line;//包含一个空的string,和一个空vector;
当然也可以,在定义是为每个成员提供初始值;
pair<string,string> author("jame","joyce");
此时author的俩个公有成员first,second,就有了值,author.first="jame",,,,author.second=joce;
还可以这样:
typedef pair<string ,string > author;
author pro("sfg","sfge");简化其声明;
make_pair(v1,v2);//以v1和v2的值创建一个新的pair对象,其元素分别是v1和v2的类型。
#include <utility> #include <iostream> #include <vector> #include <string> using namespace std; int main() { pair<string,int>pr; string str; int a; vector< pair<string,int> >vec; while (cin>>str>>a) { pr=make_pair(str,a); vec.push_back(pr); } return 0; }
map的构造函数:
map<k,v>m;//创建一个名为m的空map对象,其键和值的类型分别为k和v
map<k,v>m(m2);//创建m2的副本m,m和m2必须有相同的键类型和值类型
map<k,v>m(b,e);//创建map类型的对象m,存储迭代器b和e标记的范围内所有元素的副本,元素的类型必须能转换为pair<const k,v>
对于键的类型唯一的约束就是必须支持<操作符,至于是否支持其他的关系或想等运算则不作要求。
map类定义的类型:
map<k,v>::key_type;//map容器中,用作索引的键的类型
map<k,v>::mapped_type;//map容器中。键所关联的值的类型
map<k,v>::value_type;//一个pair类型,它的first元素具有const map<>::key_type类型,而second元素则为map<>::mapped_type类型;
在学习map接口时,需谨记value_type是pair类型,它的值成员可以修改,而建成员不能修改。
1,map迭代器进行解引用将产生map的对象。
map<string,int >mp map<string,int >::iterator mit=mp.begin(); cout<<mit->first对迭代器进行解引用将获得一个pair对象, 它的first成员存放键,为const,而second则存放值。
2,给map添加元素
定义了map容器后,下一步工作就是在容器中添加键值,该项工作可使用insert成员实现,map不支持front,push_front,push_back等操作。
1)使用下标访问map对象:
map<string,int>word;
word["anna"]=1;
此段程序将发生以下事情:
1.在word中查找键位anna的元素,没有找到
2.讲一个姓的键值对插入到word中,它的键是const string类型的对象,保存anna,而他的值则是采用直初始化,就意味着本例中的值为0
3.将这个新的键值对插入到word中
4.读取新插入的元素并将它的值赋为1;
使用下标访问不存在的元素将导致在map容器中添加一个新的元素,它的键即为下标值。
cout<<word["anna"];//通过anan访问该元素;并输出1; ++word["anna"];//访问该元素并加1; cout<<word["anna"];//输出值为2;显然,map下标操作符返回的类型与map迭代器进行解引用获得的类型不相同;map迭代器返回value_type类型的值,包括const key_type和mapped_type类型成员的pair对象;而下标操作则返回一个mapped_type类型的值。
2)下标行为的编程意义
对于map容器如果下标所表示的键在容器中不存在则添加新元素,这一特征可使程序惊人的简练;
map<string,int > word; string str; while(cin>>str) ++word[str];这段程序创建了一个map对象,用来记录单词出现的次数,while循环每次从标准输入读取一个单词,如果这是一个新单词,则在word中添加该单词为索引的新元素,如果读入的单词已经在map中则它所对应的值加1;
其中最有趣的是,在单词第一次出现时,会在word中创建并插入一个以该单词为索引的新单词,同时将它的值初始化为0;然后立即加1;所以每次在map中添加新元素时,搜统计的出现次数正好为1;
map::insert的使用:
word.insert(map<string,int>::value_type("Anna",1));
可用两种方法简化:
word.insert(make_pair("anna",1));
或:typedef map<string,int>::value_tye valType;
word.insert(valType("anna",1));
map对象中一个给定键值对应一个元素,如果试图插入的元素对应的键已经在容器中,则insert将不做任何操作。
insert返回值为包含一个迭代器和一个bool值的pair对象。
map<string,int >mp;
pair<map<string,int>::iterator,bool>ret=mp.insert(word,1);
使用下标存在一个很危险的副作用:如果该键不在map容器中那么下标操作会插入一个具有该键的新元素。有时着东西很有用但有时却带来危险
例如若是我们只想知道某元素是否存在。。。。
map容器提供俩个操作,count和find,用于检查某个键是否存在而不会插入该键;
m.count(k);//返回m中k出现的次数。
m.find(k);//如果m容器中存在k索引的元素,则返回只想该元素的迭代器,如果不存在,则返回超出末端迭代器。
从map中删除元素
map.erase(k);//删除m中键为k的元素,返回size_type类型的值。表示删除的元素个数
map.erase(p);//从m中删除迭代器p所指向的元素,p必须指向m中确实存在的元素,而且不能等于m.end;返回void
map.erase(b,e);//从m中删除一段范围内的元素该范围有迭代器对b和e标记,返回void
map同样提供begin和end运算。