第11章 关联容器
关联容器按关键字来保存和访问;与顺序容器不同
11.1 使用关联容器
map<string, size_t> word_count; string word; while(cin >> word){ ++word_count[word]; } for(const auto& w : word_count){ cout << w.first << "出现" << w.second << "次" << endl; }
11.2 关联容器概述
关联容器的迭代器都是双向的
11.2.1 定义关联容器
map<string, size_t> word_count; set<string> exclude = {"the", "but", "and", "or"}; //列表初始化 map<string, string> authors = { {"Joyce", "James"}, {"Austen", "Jane"}, {"Dickens", "Charles"} };
vector<int> ivec = {1,1,2,2,3,3,4,4}; set<int> iset(ivec.cbegin(), ivec.cend()); set<int> miset(ivec.cbegin(), ivec.cend()); cout << ivec.size() << endl; //8 cout << iset.size() << endl; //4 cout << miset.size() << endl; //8
11.2.3 pair类型
pair<string string> a; pair<string, size_t> b; pair<string, vector<int>> line; pair<string, string> author{"James", "Jotces"}; //初始化
11.3 关联容器操作
set<string>::value_type v1; //string set<string>::key_type v2; //string map<string, int>::value_type v3; //pair<const string, int> map<string, int>::key_type v4; //string map<string, int>::mapped_type v5; //int
11.3.1 关联容器迭代器
我们通常不能对关联容器使用泛型算法
set类型中元素是const的
map中的元素是pair,其第一个成员是是const的
使用关联容器定义的专用find成员会比调用泛型find快得多
练习11.16
map<string, string>family; map<const string, string>::iterator it; it->first = "AAA"; //错误,const类型 it->second = "BBB";
练习11.17
v是一个string的vector,c是一个string的muitiset
copy(v.begin(), v.end(), inserter(c, c.end())); copy(v.begin(), v.end(), back_inserter(c)); //错误, back_inserter创建一个使用push_back的迭代器 copy(c.begin(), c.end(), inserter(v, v.end())); copy(c.begin(), c.end(), back_inserter(v));
练习11.18
pair<const string, size_t>::iterator map_it;
11.3.2 添加元素
set两种方式添加元素:
- 一对迭代器
- 列表初始化
vector<int> ivec = {2,4,6,8,2,4,6,8}; set<int> set2; set2.insert(ivec.cbegin(), ivec.cend()); //4个元素 set2.insert({1,3,5,7,1,3,5,7}); //8个元素
map添加元素:
word_count.insert({word, 1}); word_count.insert(make_pair(word, 1)); word_count.insert(pair<string, size_t>(word, 1)); word_count.insert(map<string, size_t>::value_type(word, 1));
11.3.3 删除元素
关联容器提供一个额外的erase操作,它接受一个key_type参数。此版本删除所有匹配给定关键字的元素
对允许重复关键字的容器,删除元素的数量可能大于1
multimap<string, string> authors; authors.insert({"Barth, John", "Sot"}); suthors.insert({"Barth, John", "Lost"}); auto cnt = authors.erase("Barth, John");
11.3.4 map的下标操作
map<int, int> m; m[0] = 1; //添加对组元素
11.3.5 访问元素
set<int> iset = {0,1,2,3,4,5,6,7,8,9}; iset.find(1); //返回一个迭代器,指向key==1的元素 iset.find(11); //返回一个迭代器,其值等于iset.end() iset.count(1); //返回1 iset.count(11); //返回0
如果不需要计数最好用find
11.3.6 一个单词转换的map
//单词转换 void word_transform(ifstream& map_file, ifstream& input){ auto trans_map = buildMap(map_file); //保存转换规则 string text; //保存输入中的每一行 while(getline(input, text)){ //读取一行输入 istringstream stream(text); //读取每个单词 string word; bool firstword = true; //控制是否打印空格 while(stream >> word){ //该if else控制打印空格 if(firstword){ firstword = false; } else{ cout << " "; //单词间打印空格 } //transform返回它的第一个参数或其转换之后的形式 cout << transform(word, trans_map); //打印输出单词 } cout << endl; //输出完一行 } } //建立转换映射 map<string, string> buildMap(ifstream& map_file){ map<string, string> trans_map; //保存转换规则 string key; string value; //读取的第一个单词存入key中,行中剩余内容存入value中 while(map_file >> key && getline(map_file, value)){ if(value.size() > 1){ trans_map[key] = value.substr(1); } else{ throw runtime_error("no rule for" + key); } } return trans_map; } //生成转换文本 const string& transform(const string& s, const map<string, string>& m){ auto map_it = m.find(s); if(map_it != m.cend()){ return map_it->second; //找到则使用替换短语 } else{ return s; //原string } }
11.4 无序容器
- unordered_map
- unordered_set