一, pair类型
pair<T1, T2> p1; |
创建一个空pair指针,两个元素分别是T1,T2类型,采用值初始化 |
pair<T1, T2> p1(v1, v2); |
first成员初始化为v1,second成员为v2 |
make_pair(v1, v2) |
创建新的pair对象 |
p1 < p2 |
|
p1 == p2 |
|
p.first |
返回first成员 |
p.second |
返回second |
可以再定义时初始化;
pair类型的使用相当繁琐,因此用typedef来简化其声明和使用;
两个成员都是公有的;
pair<string, string> next_auth;
string first, last;
while(cin >> first >> last){
nest_auth = make_pair(fist, last);
}
二, 关联容器
1,如果希望有效地存储不同值的集合,使用set;map更适用于需要存储和修改每个键所关联的值的情况。
三, map类型
1,本质在于元素的值与某个特定的键相关联,而非通过所在位置来获取,每个键只出现一次。
2,必须包含map头文件。
3,map的声明和初始化
map<k, v> m; |
创建一个空map对象 |
map<k, v> m(m2); |
必须具有相同的键类型和值类型 |
map<k, v> m(b, e); |
存储b和e之间的所有副本。元素的类型必须能转换为pair<const k, v> |
4,map定义的类型
map<K, V>::key_type |
键类型,键为const |
map<K, V>::mepped_type |
值类型 |
map<K, V>::value_type |
pair类型,first为键类型,second为值类型 |
map迭代器进行解引用将产生pair类型的对象;
5,键类型的约束:
键不但有一个类型,而且还有一个相关的比较函数,即 < 操作符:满足与自身比较导致false,传递性,不能互相小于,互相不存在“小于”即为相等。
6,用下标访问map
如果不存在,则添加一个键为下标值的新元素;
下表操作符返回左值;
7,map::insert的使用
m.insert(e) |
e为value_type类型; 如果e.first不存在,则插入;若存在,则保持不变; 返回一个pair类型对象,包含指向键为e.first的元素的迭代器,和一个bool类型的对象,表示是否插入,即pair<map<string, int>::iterator, bool>类型。 |
m.insert(beg, end) |
beg和end中间的元素为m.value_type类型; 对所有的元素,只要该键不存在,则插入; 返回void。 |
m.insert(iter, e) |
e为m.value_type; 不存在,则创建,以iter为起点搜索新元素存储的位置; 返回迭代器指向有给定键的元素; |
传递给insert的实参太繁琐,两种方法改进:一是用make_pair(k, v),二是用typedef。
8,查找并读取map中的元素
如果只想查找或者读取元素而不想新建元素怎么办?
m.count(k) |
返回m中k的出现次数 |
m.find(k) |
存在k索引的元素,返回指向该元素的迭代器; 不存在,则返回超出末端迭代器end。 |
if (m.count(“key”))
value = m[“key”];
以上实现了读取但不插入,但实际上做了两次查找。
map<string, int>::iterator it = m.find(“key”);
if (it != m.end())
value = it->second;
以上只进行了一次查找。
9,从map对象中删除元素
m.erase(k) |
返回size_type类型,表示删除的元素个数 |
m.erase(p) |
删除迭代器p指向的元素; p必须指向存在的元素,不能为end; 返回void |
m.erase(b, e) |
b和e必须标记m中一段有效返回:e可以指向end; b和e可以相等(删除范围为空),否则b要在e之前; 返回void |
10, map对象的迭代遍历
map<string, int>::const_iterator map_it = word_count.begin();
while (map_it != word_count.end()) {
… …
++map_it;
}
四, set类型
1,set是单纯键的集合,每个键只出现一次,即对同一键多次插入实际只插入一次。
2,必须包含set头文件。
3,set的操作和map几乎相同,两个例外:没有下表操作符;没有mapped_value类型。
4,给set添加元素
s.insert(k) |
如果e.first不存在,则插入;若存在,则保持不变; 返回一个pair类型对象,包含指向键为k的元素的迭代器,和一个bool类型的对象,表示是否插入 |
s.insert(beg, end) |
beg和end中间的元素为s.value_type类型; 对所有的元素,只要该键不存在,则插入; 返回void。 |
5,获取set元素
因为没有下表操作,所以获取元素只能用find运算;如果只需判断是否存在,则用count运算。
set的键也为const,所以只能做读操作,不能做写操作。
五, multimap和multiset类型
1,允许一个键对应多个值,因此与map和set的操作有所不同。
2,multimap和multiset的操作分别与map和set的操作相同,只有一个例外:multimap不支持下标运算,因为一个键可能对应多个值。
但由于一个键可以对应多个值,因此各个操作都以不同的方式做出了修改,可以处理多个值。
3,元素的添加和删除
每次调用insert都会添加一个元素,无论该键是否存在;
带有一个键参数的erase将删除所有元素,并返回元素个数;
带有一个或一对迭代器参数的版本只删除指定的元素,并返回void类型;
4,查找元素
a,map和set中的元素是按顺序存储的;multimap和multiset中对应同一个键的元素将相邻存放。
b,使用find和count操作
typedef multimap<K, V>::size_type sz_type;
sz_type entries = multimap.count(k);
multimap<K, V>::iterator iter = multimap.find(k);
for (sz_type cnt = 0; cnt != endl; ++cnt, ++iter){… …}
c, 面向迭代器的解决方案
m.lower_bound(k) |
返回迭代器,指向键不小于k的第一个元素 |
m.upper_bound(k) |
返回迭代器,指向键大于k的第一个元素 |
适用于map和set但更常用于multimap和multiset;
调用这两个函数将产生一个迭代器范围,指示出所关联的所有元素;
如果该键不存在,则返回指向该键应该插入的位置的迭代器;
返回值有可能是超出末端迭代器;
typedef multimap<K, V>::iterator iter;
iter beg = m.lower_bound(k),
end = m.upper_bound(k);
while (beg != end){
… …
++beg;
}
d,equal_range函数
m.equal_range(k) |
返回一个迭代器的pair对象: first成员等价于m.lower_bound(k); second对象等价于m.upper_bound(k)。 |
pair<iter, iter> pos = m.equal_range(k);
while(pos.first != pos.second){
cout << pos.first->second << endl;
++pos.first;
}