C++ Primer 0x0B 练习题解
Posted 鱼竿钓鱼干
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ Primer 0x0B 练习题解相关的知识,希望对你有一定的参考价值。
📔 C++ Primer 0x0B 练习题解
推荐阅读 《C++ Primer 5th》知识点总结&练习题解
11.1 使用关联容器
11.1 描述
map
和vector
的不同
map
是关联容器,vector
是顺序容器- 关联容器不支持顺序容器的位置相关的操作如
push_front
或push_back
- 关联容器的迭代器都是双向的,
vector
是随机迭代器
11.2 分别给出最适合使用
list
、vector
、deque
、map
以及set
的例子。
list
:双向链表,适合频繁插入删除元素的场景。vector
:适合频繁访问元素的场景。deque
:双端队列,适合频繁在头尾插入删除元素的场景。map
:字典。set
:适合有序不重复的元素的场景。
11.3 编写你自己的单词计数程序。
#include <map>
#include <string>
#include <iostream>
int main()
std::map<std::string,int>mp;
std::string s;
while(std::cin >> s)mp[s]++;
for(const auto& e:mp)
std::cout << e.first << " " << e.second << std::endl;
return 0;
11.4 扩展你的程序,忽略大小写和标点。例如,“example.”、"example,"和"Example"应该递增相同的计数器。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
int main()
std::map<std::string,int>mp;
std::string s;
while(std::cin >> s)
for(auto &c:s)c = tolower(c);
s.erase(std::remove_if(s.begin(), s.end(),ispunct),s.end());
++mp[s];
for(const auto& e:mp)
std::cout << e.first << " " << e.second << std::endl;
return 0;
11.2 关联容器概述
11.2.1 定义关联容器
11.5 解释
map
和set
的区别。你如何选择使用哪个?
- 定义一个
map
,必须既指明关键字类型又指明值类型 - 定义一个
set
,只需指明关键字类型,因为set
中没有值
选择
map
:字典。set
:适合有序不重复的元素的场景。
11.6 解释
set
和list
的区别。你如何选择使用哪个?
set
关联容器,是有序不重复集合,底层实现是红黑树
list
顺序容器,是无序可重复集合,底层实现是链表
11.7 定义一个
map
,关键字是家庭的姓,值是一个vector
,保存家中孩子(们)的名。编写代码,实现添加新的家庭以及向已有家庭中添加新的孩子。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
int main()
std::map<std::string,std::vector<std::string>>mp;
std::string family_name,children_name;
while(std::cin >> family_name >> children_name)
mp[family_name].push_back(children_name);
return 0;
11.8 编写一个程序,在一个
vector
而不是一个set
中保存不重复的单词。使用set
的优点是什么?
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
int main()
std::vector<std::string>words;
std::string s;
while(std::cin >> s)words.push_back(s);
std::sort(words.begin(),words.end());
words.erase(std::unique(words.begin(),words.end()),words.end());
for(const auto &s:words)std::cout << s << std::endl;
return 0;
set
本身就是有序不重复集合
11.2.2 关键字类型的要求
11.9 定义一个
map
,将单词与一个行号的list
关联,list
中保存的是单词所出现的行号。
std::map<std::string, std::list<std::size_t>> mp;
11.10 可以定义一个
vector<int>::iterator
到int
的map
吗?list<int>::iterator
到int
的map
呢?对于两种情况,如果不能,解释为什么。
vector<int>::iterator
到 int
的map
,可以定义
list<int>::iterator
到 int
的map
,不可以定义
有序容器要求所提供的操作必须在关键字类型上定义一个严格弱序(可以自己定义)
因为map
的键必须实现 <
操作,list
的迭代器不支持比较运算。
11.11 不使用
decltype
重新定义bookstore
。
multiset<Sales_data,bool (*)(const Sale_data&,const Sales_data&)>bookstore(compareIsbn);
11.2.3 pair 类型
11.12 编写程序,读入
string
和int
的序列,将每个string
和int
存入一个pair
中,pair
保存在一个vector
中。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
int main()
std::string s;int i;
std::vector<std::pair<std::string,int>>v;
while(std::cin >> s >> i)
v.push_back(make_pair(s,i));
for(auto p:v)
std::cout << p.first << " " << p.second << std::endl;
return 0;
11.13 在上一题的程序中,至少有三种创建
pair
的方法。编写此程序的三个版本,分别采用不同的方法创建pair
。解释你认为哪种形式最易于编写和理解,为什么?
v.push_back(make_pair(s,i));
v.push_back(s,i);//最容易理解
v.push_back(std::pair<std::string,int>(s,i));
11.14 扩展你在11.2.1节练习中编写的孩子姓达到名的
map
,添加一个pair
的vector
,保存孩子的名和生日。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
int main()
std::map<std::string,std::vector<std::pair<std::string,std::string>>>mp;
std::string family_name,children_name,birthday;
while(std::cin >> family_name >> children_name >> birthday)
mp[family_name].push_back(children_name,birthday);
return 0;
11.3 关联容器操作
11.3.1 关联容器迭代器
11.15 对一个
int
到vector<int>的map
,其mapped_type
、key_type
和value_type
分别是什么?
mapped_type
:vector<int>的map
key_type
:int
value_type
:pair<const int,vector<int>
11.16 使用一个
map
迭代器编写一个表达式,将一个值赋予一个元素。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
int main()
std::map<int,int>mp=1,10,2,9,3,8;
std::map<int,int>::iterator iter = mp.begin();
std::cout << mp[1] << std::endl;
(*iter).second = 1;
std::cout << mp[1] << std::endl;
iter->second = 2;
std::cout << mp[1] << std::endl;
return 0;
11.17 假定
c
是一个string
的multiset
,v
是一个string
的vector
,解释下面的调用。指出每个调用是否合法:
copy(v.begin(), v.end(), inserter(c, c.end()));
copy(v.begin(), v.end(), back_inserter(c));//不合法,multiset关联容器不支持push_back
copy(c.begin(), c.end(), inserter(v, v.end()));
copy(c.begin(), c.end(), back_inserter(v));
11.18 写出第382页循环中
map_it
的类型,不要使用auto
或decltype
。
map<std::string,std::size_t>::const_iterator
注意迭代器是不能加const
的,不要写成下面这样
cosnt map<std::string,std::size_t>::iterator
11.19 定义一个变量,通过对11.2.2节中的名为
bookstore
的multiset
调用begin()
来初始化这个变量。写出变量的类型,不要使用auto
或decltype
。
using compareType = bool (*)(const Sales_data &, const Sales_data &);
std::multiset<Sales_data, compareType> bookstore(compareIsbn);
std::multiset<Sales_data, compareType>::iterator c_it = bookstore.begin();
11.3.2 添加元素
11.20 重写11.1节练习的单词计数程序,使用
insert
代替下标操作。你认为哪个程序更容易编写和阅读?解释原因。
#include <map>
#include <string>
#include <iostream>
int main()
std::map<std::string,int>mp;
std::string s;
while(std::cin >> s)
auto result = mp.insert(s,1);
if(!result.second)
++result.first->second;
for(const auto& e:mp)
std::cout << e.first << " " << e.second << std::endl;
return 0;
下标操作更容易
- 对一个
map
使用下标操作,其行为与数组或vecotr
上的下标操作很不相同,使用一个不在容器中的关键字作为下标,会添加一个具有此关键字的元素到map
中 c[k]
返回关键字为k
的元素,如果k
不在c
中则添加一个关键字为k
的元素,对其值进行值初始化
11.21 假定
word_count
是一个string
到size_t
的map
,word
是一个string
,解释下面循环的作用:
while (cin >> word)
++word_count.insert(word, 0).first->second;
等价
while(cin >> word)
++word_count[word];
11.22 给定一个
map<string, vector<int>>
,对此容器的插入一个元素的insert
版本,写出其参数类型和返回类型。
-
参数类型:
std::pair<std::string,std::vector<int>
-
返回类型:
std::pair<std::map<std::string,std::vector<int>>::iterator,bool
11.23 11.2.1节练习中的
map
以孩子的姓为关键字,保存他们的名的vector
,用multimap
重写此map
。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
int main()
std::multimap<std::string,std::string>mp;
std::string family_name,children_name;
while(std::cin >> family_name >> children_name)
mp.emplace(family_name,children_name);
return 0;
11.3.4 map的下标操作
11.24 下面的程序完成什么功能?
map<int, int> m;
m[0] = 1;//添加key-value:0-1
c[k]
返回关键字为k
的元素,如果k
不在c
中则添加一个关键字为k
的元素,对其值进行值初始化
11.25 对比下面的程序与上一题程序
vector<int> v;
v[0] = 1;//下标越界访问
对一个map
使用下标操作,其行为与数组或vecotr
上的下标操作很不相同,使用一个不在容器中的关键字作为下标,会添加一个具有此关键字的元素到map
中
11.26 可以用什么类型来对一个
map
进行下标操作?下标运算符返回的类型是什么?请给出一个具体例子——即,定义一个map
,然后写出一个可以用来对map
进行下标操作的类型以及下标运算符将会返会的类型。
std::map<int, std::string> m = 1,"ss" , 2,"sz" ;
using KeyType = std::map<int, std::string>::key_type;
using ReturnType = std::map<int, std::string>::mapped_type;
- 对
map
进行下标操作会得到一个mapped_type
对象,解引用map
迭代器时,会得到一个value_type
对象,这与vector
、string
是不同的 map
的下标运算符返回的是一个左值,我们既可以读也可以写元素
11.3.5 访问元素
11.27 对于什么问题你会使用
count
来解决?什么时候你又会选择find
呢?
允许重复用count
不允许重复用find
11.28 对一个
string
到int
的vector
的map
,定义并初始化一个变量来保存在其上调用find
所返回的结果。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
int main()
std::map<std::string,std::vector<int>>mp="a",1,2,3,"ab",1,2,"abc",3,4;
auto result = mp.find("abc");
if(result != mp.end())
std::cout << result->first << " " << std::endl;
for(auto i:result->second)std::cout << i << " ";
return 0;
11.29 如果给定的关键字不在容器中,
upper_bound
、lower_bound
和equal_range
分别会返回什么?
-
c.lower_bound(k)
返回一个迭代器,指向第一个关键字不小于k
的元素,如果关键字不在容器中,则lower_bound
会返回关键字的第一个安全插入点(不影响容器中元素顺序的插入位置) -
可以通过
lower_bound
和upper_bound
,获得一对迭代器对形成的范围,表示具有该关键字的元素的范围,如果没有与给定关键字匹配的元素,lower_bound
和upper_bound
返回相同的迭代器 -
c.equal_range(k)
返回一个迭代器pair
表示关键字等于k
的元素范围,若k
不存在,pair
的两成员均等于c.end()
(两个关键字都指向可以插入的位置)
11.30 对于本节最后一个程序中的输出表达式,解释运算对象
pos.first->second
的含义。
c.equal_range(k)
返回一个迭代器pair
表示关键字等于k
的元素范围,若k
不存在,pair
的两成员均等于c.end()
(两个关键字都指向可以插入的位置)
pos
是一个pair
pos.first
是一个指向匹配关键字元素的迭代器
pos.first->second
匹配关键字元素的关联也是个pair
,访问这个pair
的第二个成员
11.31 编写程序,定义一个作者及其作品的
multimap
。使用find
在multimap
中查找一个元素并用erase
删除它。确保你的程序在元素不在map
中时也能正常运行。
#include <cctype>
#include <map>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
int main()
std::multimap<std::string,std::string>authors
"A","123","B","456","C","789",
"A","abc","B","def","C","ghi"
;
auto found = authors.find("B");
auto count = authors.count("B"<以上是关于C++ Primer 0x0B 练习题解的主要内容,如果未能解决你的问题,请参考以下文章