关联容器概述
map 键值对(一个键对应一个值,键不可重复。如字典,单词是键,词义为值)
set 键对(键的集合,键不可重复)
multimap 键值对(一个键对应多个值,键不可重负)
multiset 键对(键的集合,键可以重复)
特点
容器元素根据键的次序进行排列。
pair类型的操作
① pair<T1, T2> p1
如pair<string, string> poetry;pair<string, int> word_count
② pair<T1, T2> p1(v1, v2)
③ make_pair(v1, v2)
如pair<string, string> next_auth;
string first, last;
while (cin >> first >> last)
next_auth = make_pair(first, last);
① p1 < p2
② p1 == p2
③ p.first
④ p.second
使用typedef来简化pair的声明
typedef pair<string, string> Author;
Author TheAuthor("James","King");
map 概述
①map 类型可理解为关联数组(associative array):可使用键作为下标来获取一个值,正如内置数组类型一样。值与键相关,而不与元素在数组中的位置相关。
②value_type 为pair类型
map的构造函数
map<k, v> m
map<k, v> m(m2)
map<k, v> m(b, e); //存储迭代器 b 和 e 标记的范围内所有元素的副本。元素的类型必须能转换为 pair<const k, v>;
map定义的类型
map<K, V>::key_type
map<K, V>::mapped_type
map<K, V>::value_type //一个 pair 类型,它的 first 元素具有 const map<K, V>::key_type 类型,而 second 元素则为 map<K, V>::mapped_type 类型
对迭代器进行解引用
对迭代器进行解引用时,将获得一个引用,指向容器中一个 value_type 类型的值。对于 map 容器,其 value_type 是 pair 类型:
map<string, int>::iterator map_it = word_count.begin();
cout << map_it->first;
cout << " " << map_it->second;
map_it->first = "new key";
++map_it->second;
下标操作的特点
1返回值
下标操作符则返回一个 mapped_type 类型的值。这和迭代器的返回类型不同。
map 迭代器返回 value_type 类型的值。它是pair对象,包含 const key_type 和 mapped_type。
2特性
对于 map 容器,如果下标所表示的键在容器中不存在,则添加新元素
例
map<string, int> word_count;
while (cin >> word)
++word_count[word];
map::insert()
m.insert(e)
//e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则插入一个值为 e.second 的新元素;如果该键在 m 中已存在,则保持 m 不变。该函数返回一个 pair 类型对象,包含指向键为 e.first 的元素的 map 迭代器,以及一个 bool 类型的对象,表示是否插入了该元素
m.insert(beg, end)
//插入beg到end这个范围中的元素
m.insert(iter, e)
//e是value_type类型,从iter开始插入e。
例1
word_count.insert(map<string, int>::value_type("Anna", 1));
简化方式1
word_count.insert(make_pair("Anna", 1));
简化方式2
typedef map<string,int>::value_type valType;
word_count.insert(valType("Anna", 1));
例2统计词频
map<string, int> word_count;
while (cin >> word)
{
pair<map<string, int>::iterator, bool> ret = word_count.insert(make_pair(word, 1));
if (!ret.second)
++ret.first->second; //理解为ret的first的second进行了加1的操作
}
查找map中的元素
m.count(k)//返回出现次数
m.find(k)//存在则返回指向该元素的value_type,否则返回超出末端的迭代器。
例
int occurs = 0;
map<string,int>::iterator it = word_count.find("foobar");
if (it != word_count.end())
occurs = it->second;
删除元素
m.erase(k)
m.erase(p)
m.erase(b.e)
对map对象的迭代遍历
map<string, int>::const_iterator map_it = word_count.begin();
while (map_it != word_count.end())
{
cout << map_it->first << " occurs "<< map_it->second << " times" << endl;
++map_it;
}
set类型
set与map的区别
set 不支持下标操作符,而且没有定义 mapped_type 类型。
在 set 容器中,value_type 不是 pair 类型,而是与 key_type 相同的类型。它们指的都是 set 中存储的元素类型。这一差别也体现了 set 存储的元素仅仅是键,而没有所关联的值。
与 map 一样,set 容器存储的键也必须唯一,而且不能修改。
set应用
创建单词排除集,并统计一个文本中,不在排除集中的单词的数量
void restricted_wc(ifstream &remove_file, map<string, int> &word_count)
{
set<string> excluded;
string remove_word;
while (remove_file >> remove_word)
excluded.insert(remove_word);
string word;
while (cin >> word)
if (!excluded.count(word))
++word_count[word];
}
multimap, multiset
multiset 和 multimap 类型则允许一个键对应多个实例.
multimap 和 multiset 所支持的操作分别与 map 和 set 的操作类似。
但multimap 不支持下标运算。因为某个键可能对应多个值。