11.1
map是关联容器,包括关键字和值。
vector是顺序容器
11.2
list:适合用于实现双向链表,例如,实现队列时,可以使用list来存储元素并在队列头和尾进行插入和删除操作。
vector:适合用于需要快速随机访问元素的情况。例如,实现动态数组时,可以使用vector来存储元素。
deque:适合用于需要在容器的两端进行插入和删除操作的情况。例如,实现双端队列时。
map:适合用于存储键值对,并需要按键进行快速查找的情况。例如,实现字典时。
set:适合用于需要存储元素并支持快速查找、插入和删除操作的情况。例如,实现一个集合时。
11.3
#include<iostream>
#include<string>
#include<map>
#include<set>
int main(int argc, char**argv)
{
std::map<std::string, size_t>word_count;
std::set<std::string> exclude = { "The","But","And","Or","An","A","the","but","and","or","an","a" };
std::string word;
while (std::cin >> word)
{
if (exclude.find(word) == exclude.end())
++word_count[word];
}
for (const auto &i : word_count)
std::cout << i.first << " occurs: " << i.second << ((i.second > 1) ? " times" : " time") << std::endl;
return 0;
}
11.4
#include<iostream>
#include<string>
#include<map>
#include<set>
#include<algorithm>
int main(int argc, char**argv)
{
std::map<std::string, size_t>word_count;
std::set<std::string> exclude = { "The","But","And","Or","An","A","the","but","and","or","an","a" };
std::string word;
while (std::cin >> word)
{
word.erase(find_if(word.begin(), word.end(), ::ispunct), word.end());
for_each(word.begin(), word.end(), [](char &c) {return c = tolower(c); });
if (exclude.find(word) == exclude.end())
++word_count[word];
}
for (const auto &i : word_count)
std::cout << i.first << " occurs: " << i.second << ((i.second > 1) ? " times" : " time") << std::endl;
return 0;
}
11.5
map中有关键字—值对
set中只有关键字
11.6
list是双向链表的顺序容器,在插入和删除上很快。
set是关联式容器。
11.7
#include<iostream>
#include<vector>
#include<string>
#include<map>
int main(int argc, char**argv)
{
std::map<std::string, std::vector<std::string>> family;
std::string first_name, last_name;
while (std::cin >> first_name)
{
family[last_name].push_back(first_name);
}
for (const auto &i : family)
{
std::cout << i.first << std::endl;
for (const auto &j : i.second)
{
std::cout << j << " ";
}
}
return 0;
}
11.8
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
int main(int argc, char**argv)
{
std::vector<std::string> v;
std::string str;
while (std::cin >> str)
{
if (find(v.begin(), v.end(), str) == v.end())
{
v.push_back(str);
}
}
for (auto &i : v)
std::cout << i << " ";
return 0;
}
11.9
std::map<std::string, std::list<int>> map;
11.10
对于有序容器—map、multimap、set以及multiset,关键字类型必须定义元素比较的方法。 默认情况下,标准库只用关键字类型的<运算符来比较两个关键字。
显然,vector是有顺序的,list是双向链表,五顺序的。
11.11
#include <set>
#include <iostream>
#include <string>
#include "../ch07_Classes/Sales_data_ex26.h"
// 转载自https://blog.csdn.net/qq_24898229/article/details/123796603?spm=1001.2014.3001.5502
bool compareIsbn(const Sales_data &sales_data1, const Sales_data &sales_data2)
{
return sales_data1.isbn() < sales_data2.isbn();
}
int main()
{
using COMPAREISBN = bool (*)(const Sales_data &sales_data1, const Sales_data &sales_data2);
std::multiset<Sales_data, COMPAREISBN> bookstore(compareIsbn);
return 0;
}
11.12
#include<iostream>
#include<map>
#include<utility>
#include<vector>
#include<string>
int main()
{
std::vector<std::pair<std::string, int>> v;
int i;
std::string s;
while (std::cin >> s >> i)
v.push_back(make_pair(s, i));
for (auto i : v)
{
std::cout << i.first << " " << i.second << std::endl;
}
return 0;
}
11.13
#include<iostream>
#include<map>
#include<utility>
#include<vector>
#include<string>
int main()
{
std::vector<std::pair<std::string, int>> v;
int i;
std::string s;
while (std::cin >> s >> i)
//v.push_back(pair<string, int>(s, i));
//v.push_back({ s,i });
v.push_back(make_pair(s, i));
for (auto i : v)
{
std::cout << i.first << " " << i.second << std::endl;
}
return 0;
}
make_pair最容易理解和编写。
11.14
#include<iostream>
#include<vector>
#include<string>
#include<utility>
#include<map>
int main(int argc, char**argv)
{
std::map < std::string, std::vector<std::pair<std::string, std::string>>> family;
std::string first_name, last_name, birth;
while (std::cin >> first_name>>birth)
family[last_name].push_back(make_pair(first_name,birth));
for (const auto &i : family)
{
std::cout << i.first << std::endl;
for (const auto &j : i.second)
std::cout << j.first << " " << j.second << std::endl;
}
return 0;
}
11.15
对于std::map<int,std::vector> m
mapped_type: vector
key_type: int
value_type: pair<const int,vector>
11.16
/*在C++的STL中,map是一种关联式容器,其底层实现是红黑树,而迭代器是用来遍历容器内元素的。
在map中,每个元素都是一个pair类型的键值对,其中first表示键,second表示值。
由于map中的元素并不是一个类对象,而是一个pair对象,因此需要使用->来获取其中的元素值。
当使用.运算符时,编译器会将其解释为对pair对象进行操作,而pair对象没有对应的成员变量,因此会出现编译错误。因此,必须使用->运算符来访问map中的元素值。
需要注意的是,C++17标准引入了try_emplace和insert_or_assign方法,这些方法可以直接使用.来访问元素值。但这些方法不适用于旧版本的C++标准或者不支持这些方法的编译器。
*/
#include<iostream>
#include<string>
#include<map>
int main(int argc, char**argv)
{
std::map<int, std::string> map;
map[214] = "ogiso";
auto iter = map.begin();
iter->second = "setsuna";
std::cout << iter->first << " " << iter->second << std::endl;
return 0;
}
11.17
copy(v.begin(), v.end(), inserter(c, c.end())); //合法
copy(v.begin(), v.end(), back_inserter©); //非法,set中没有push_back()
copy(c.begin(), c.end(), inserter(v, v.end())); //合法
copy(c.begin(), c.end(), back_inserter(v)); //合法
11.18
map<string,size_t>::const_iterator
11.19
using compareType = bool (*)(const Sales_data &lhs, const Sales_data &rhs);
std::multiset<Sales_data, compareType> bookstore(compareIsbn);
std::multiset<Sales_data, compareType>::iterator c_it = bookstore.begin();
11.20
#include<iostream>
#include<string>
#include<map>
#include<set>
#include<algorithm>
int main(int argc, char**argv)
{
std::map<std::string, size_t>word_count;
std::set<std::string> exclude = { "The","But","And","Or","An","A","the","but","and","or","an","a" };
std::string word;
while (std::cin >> word)
{
auto ret = word_count.insert({ word,1 });
if (!ret.second)
++ret.first->second;
}
for (const auto &i : word_count)
std::cout << i.first << " occurs: " << i.second << ((i.second > 1) ? " times" : " time") << std::endl;
return 0;
}
使用insert更简单
11.21
当输入给到cin时,在word_count中插入{word,0},返回pair。
对pair的first部分,即map容器
对map的second的元素,即size_t的对象进行++操作.
11.22
std::pair<std::map<std::string, std::vector<int>>::iterator,bool> it = vec.insert({ "Wang",{1,2,3} });
11.23
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<utility>
int main(int argc, char**argv)
{
std::multimap<std::string, std::vector<std::string>> family;
std::string first_name, last_name;
while (std::cin >> first_name >> last_name)
{
family.insert({ last_name,{first_name} });
}
for (const auto &i : family)
{
std::cout << i.first << std::endl;
for (const auto &j : i.second)
{
std::cout << j << " ";
}
std::cout << std::endl;
}
return 0;
}
11.24
初始化一个int,int类型的map,添加{0,1}.
11.25
将1赋值给*v.begin()。
11.26
可以用key_type对一个map进行下标操作;
下标操作返回mapped_type;
11.27
对于数数的问题用count;
对于查找特定元素的问题用find.
11.28
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<utility>
int main(int argc, char**argv)
{
std::map<std::string, std::vector<int>> map ={ std::string("suki"),{0,1,2,3,4,5,6,7,8,9} };
auto result = map.find("suki");
return 0;
}
11.29
如果元素不在multimap中,则lower_bound和upper_bound会返回相等的迭代器——指向一个不影响排序的关键字插入位置。
equal_range的两个迭代器都指向关键字可以插入的位置。
11.30
pos返回的时一个pair<map<string,size_t>::iterator,bool>的pair
pos.first是指向Pair中的map<string,size_t>::iterator的迭代器
pos.first->second是因为map中的元素是以pair对象的方式存在的,不是类的对象,所以使用second来获取其中的size_t元素值。
11.31
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<utility>
int main(int argc, char**argv)
{
std::multimap<std::string, std::string> authors;
authors.insert({ "Barth John", "Sot feed factor" });
authors.insert({ "Barth John", "The Game Of Thorean" });
auto rec = authors.find("Barth");
if (rec != authors.end())
{
auto num = authors.erase("Barth John");
std::cout << "Successfully deleted:" << num << (num > 1 ? " books" : " book") << std::endl;
}
else
std::cerr << "Cannot find the book!" << std::endl;
return 0;
}
11.32
#include<algorithm>
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<utility>
int main(int argc, char**argv)
{
std::multimap<std::string, std::string> authors;
authors.insert({ "Barth John", "Sot feed factor" });
authors.insert({ "Barth John", "The Game Of Thorean" });
authors.insert({ "Alan", "CppPrimer" });
authors.insert({ "Yaoyang Wang", "I just wanna live in the infinite fantasy" });
//将multima转换为vector进行排序
std::vector<std::pair<std::string, std::string>> ordered_authors(authors.begin(), authors.end());
sort(ordered_authors.begin(), ordered_authors.end());
for (auto &author : ordered_authors)
std::cout << author.first << " :" << author.second << std::endl;
return 0;
}
11.33
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include<map>
std::map<std::string, std::string> buildMap(std::ifstream &map_file)
{
std::map<std::string, std::string> trans_map;
std::string key,value;
while (map_file >> key && getline(map_file, value))
{
if (value.size() > 1)
trans_map[key] = value.substr(1);
else
throw std::runtime_error("No rule for" + key);
}
return trans_map;
}
const std::string & transform(const std::string &s, const std::map<std::string, std::string> &m)
{
auto map_it = m.find(s);
if (map_it != m.cend())
return map_it->second;
else
return s;
}
void word_transform(std::ifstream &map_file, std::ifstream &input) //调用buildmap和transform
{
auto trans_map = buildMap(map_file); //保存转换规则
std::string text;
while (getline(input, text))
{
std::istringstream stream(text);
std::string word;
bool firstword = true;
while (stream >> word)
{
if (firstword)
firstword = false;
else
std::cout << " ";
std::cout << transform(word, trans_map);
}
std::cout << std::endl;
}
}
int main(int argc,char **argv)
{
std::ifstream map_file(argv[1]);
std::ifstream input(argv[2]);
word_transform(map_file,input);
return 0;
}
11.34
当map中没有这个元素时会插入元素,与预期不符;
11.35
这里没有影响,因为不是mutimap,对于重复出现的key,会对value进行覆盖。
11.36
没有抛出异常,但是他也不会被替换,会保留一个空行。
11.37
无序容器使用了哈希函数和关键字类型的==运算符,在关键字类型的元素没有明显的序关系的情况下,维护元素的序代价非常高昂,此时无序容器很有用。
11.38
// 单词计数
#include<iostream>
#include<string>
#include<unordered_map>
int main(int argc, char**argv)
{
std::unordered_map<std::string, size_t>word_count;
std::string word;
while (std::cin >> word)
{
++word_count[word];
}
for (const auto &i : word_count)
std::cout << i.first << " occurs: " << i.second << ((i.second > 1) ? " times" : " time") << std::endl;
return 0;
}
//转换程序 把map换成unordered_map