c++Primer第11章:关联容器(习题解答)

前言

这些大部分都是自己做出来的,小部分参考了答案,可供大家参考

11.1节练习

11.1:描述mapvector的不同
答:
map是表示哈希表,vector相当于数组
11.2:分别给出最适合使用listvector、deque、map、以及set的例子
答:
list适用于链表,vector适用于数组类,deque是双端队列,map是哈希表,set是集合
11.3:编写你自己的单词计数程序
11.4:扩展你的程序,忽略大小写和标点,
答:上面两题一起

//map是表示哈希表,vector相当于数组
//list适用于链表,vector适用于数组类,deque是双端队列,map是哈希表,set是集合
#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
unordered_map<string, int>mp;
int main() {
	string str;
	while (cin>>str) {
		for (int i = 0;i < str.size();i++) {
			if (str[i] >= 'A' && str[i] <= 'Z') {
				str[i] += 32;
			}
			if (iswpunct(str[i]) ){
				str.erase(str.begin() + i);
			}
		}
		mp[str]++;
	}
	for (auto num : mp) {
		cout << num.first << " ";
		cout << num.second << endl;
	}
	return 0;
}

11.2.1节练习

11.5:解释mapset的区别,你应该选择哪个
答:map是哈希表,set是集合
11.6:解释setlist的区别
答:map是哈希表,list是链表
11.7:定义一个map,关键字是家庭的姓,值是一个vector,保存家中孩子们的明。编写代码,实现添加新的家庭以及向已有的家庭添加新的孩子。
答:

//map是表示哈希表,vector相当于数组
//list适用于链表,vector适用于数组类,deque是双端队列,map是哈希表,set是集合
#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
unordered_map<string, vector<string>>mp;
void add_family(string name,vector<string>son) {
	mp[name] = son;
}
void add_son(string family, string son_name) {
	mp[family].emplace_back(son_name);
}
int main() {
	string str;
	vector<string>name = { "jone","job" };
	add_family("mr", name);
	add_son("mr", "hello");
	return 0;
}

11.8:编写一个程序,在一个vector而不是一个set中保存不重复的单词,使用·set的优点是啥
答:

//map是表示哈希表,vector相当于数组
//list适用于链表,vector适用于数组类,deque是双端队列,map是哈希表,set是集合
#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
unordered_map<string, vector<string>>mp;
void add(vector<int>& ans,int num) {
	if (ans.empty()) {
		ans.emplace_back(num);
		return;
	}
	else 
		for (auto curr : ans) {
			if (curr == num)return;
		}
	ans.emplace_back(num);
}
int main() {
	int num;
	vector<int>ans;
	while (cin>>num) {
		add(ans, num);
	}
	for (auto& num : ans)cout << num << " ";
	return 0;
}
**set的效率更高**

11.9节练习

11.9:定义一个map,将单词与一个行号的list相关联,list保存的是单词所出现的行号。
11.10:可以定义一个vector< int> ::iterator到int的map吗,list< int >::iterator到int的map
答:
前一个可以,后一个不可以,map是有序的,则其关键字需要支持有序
11.11:不使用decltype重新定义bookstore
答:

typedef bool (*pf)(const sale_data&, const sale_data&);
multiset<sale_data, pf>bookstore(pf);

11.12:编写程序,读入stringint的序列,将每个stringint存入一个pair中,pair保存在一个vector
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
#include<set>
using namespace std;
int main() {
	string str;
	int num;
	vector<pair<string, int>>ans;
	while (cin >> str && cin >> num) {
		pair<string, int>temp(str, num);
		ans.emplace_back(temp);
		cout << ans.back().first << " " << ans.back().second;
	}
	return 0;
}

11.13:在上一题的程序中,至少有三种创建pair的方法。编写此程序的三个版本,分别采用不同的方法创建pair。解释你认为哪种形式比较易于理解
答:

		pair<string, int>temp(str, num);
		pair<string, int>temp = { str,num };
		ans.emplace_back(make_pair(str, num));

第一种比较好理解吧
11.14:扩展你的374页编写的孩子姓到名的map,添加一个pairvector,保存孩子的名和生日
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
unordered_map<string, vector<pair<string,int>>>mp;
void add_family(string name, vector<pair<string,int>>son) {
	mp[name] = son;
}
void add_son(string family, string son_name,int age) {
	mp[family].emplace_back(make_pair(son_name, age));
}
int main() {
	string str;
	vector<pair<string, int>>child = { make_pair("name",17) };
	add_family("mr", child);
	add_son("mr", "hello",34);
	for (auto num : mp) {
		cout << num.first << " ";
		for (auto curr : num.second) {
			cout << curr.first << " " << curr.second << " ";
		}
	}
	return 0;
}

11.3.1节练习

11.15:对一个intvector< int > 的mp,其mapped_typekey_typevalue_tyep分别是什么
答:mapped_type是vector< int> 类型,key_type是int,value_type是pair<int,mapped_type>类型
11.16:使用一个map迭代器编写一个表达式,将一个值赋予一个元素。
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
unordered_map<string, vector<pair<string,int>>>mp;
int main() {
	map<int, int>ans = { {1,2} };
	ans.begin()->second = 4;
	for (auto num : ans)cout << num.second;
	return 0;
}

11.17:假定c是一个stringmultisetv是一个stringvector,解释下面的调用。指出每个调用是否合法

copy(v.begin(),v.end(),inserter(c,c.end());
copy(v.begin(),v.end(),back_inserter(c));
copy(c.begin(),c.end(),inserter(v,v.end());
copy(c.begin(),c.end(),back_inserter(v));

答:1.不合法,2.不合法,3.合法,4.合法,因为set的迭代器都是const,不可以对其修改
11.18:写出382页循环中map_it类型,不要使用autodecltype
答:pair<const string,size_t>
11.19:定义一个变量,通过对378页中的名为bookstoremultiset调用begin()来初始化这个变量的类型,不要使用auto或者decltype
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
#include<set>
using namespace std;
unordered_map<string, vector<pair<string,int>>>mp;
class sale_data {
private:
	int value;
public:
	int get_value() {
		return value;
	}
};
typedef sale_data(*fd);
bool cmpareIsbn(sale_data a, sale_data  b) {
	return a.get_value() > b.get_value();
}
typedef bool(*pf)(sale_data a,sale_data b);
int main() {
	sale_data a;
	multiset<sale_data, pf>ans = { a };
	auto iter = ans.begin();
	multiset<sale_data, pf>::iterator iter = ans.begin();
	return 0;
}

11.3.2节练习

11.20:重写单词计数程序,使用insert代替下标操作。你认为哪个程序跟容易编写和阅读?解释原因

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
unordered_map<string, int>mp;
int main() {
	string str;
	while (cin >> str) {
		for (int i = 0;i < str.size();i++) {
			if (str[i] >= 'A' && str[i] <= 'Z') {
				str[i] += 32;
			}
			if (iswpunct(str[i])) {
				str.erase(str.begin() + i);
			}
		}
		auto iter = mp.insert({ str,1 });
		if (!iter.second) {
			iter.first->second++;
		}
	}
	for (auto num : mp) {
		cout << num.first << " ";
		cout << num.second << endl;
	}
	return 0;
}

11.21:假定word_count是一个stringsize_tmapword是一个string,解释下面循环的作用

while(cin>>word)
	++word_count.insert({word,0}).first->second;

答:插入函数返回pair迭代器,也就是待插入元素,在word中找是否有相同键值的元素,如果有,就让其关键字对应的值加一
11.22:给定一个map<string,vector< int >>,对此容器的插入一个元素的insert版本,写出其参数版本类型和返回类型
答:参数类型是string,int类型,返回类型是其迭代器
11.23:378页中的map以孩子的姓为关键字,保存他们的名的vector,用multimap重写map
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
unordered_multimap<string, vector<pair<string, int>>>mp;
void add_family(string name, vector<pair<string, int>>son) {
	 mp.insert(make_pair(name, son));
}
void add_son(string family, string son_name, int age) {
	vector<pair<string, int>>temp = { {son_name,age} };
	mp.insert(make_pair(family,temp));
}
int main() {
	string str;
	vector<pair<string, int>>child = { make_pair("name",17) };
	add_family("mr", child);
	add_son("mr", "hello", 34);
	add_son("mr", "int", 78);
	for (auto num : mp) {
		cout << num.first << " ";
		for (auto curr : num.second) {
			cout << curr.first << " " << curr.second << " ";
		}
	}
	return 0;
}

11.3.4节练习

11.24:下面的程序完成什么功能?

map<int,int>m;
m[0]=1;

答:哈希表利用下标加入元素
11.25:对比下面程序与上一题程序

vector<int>v;
v[0]=1;

答:这段代码没有初始化,也没有分配内存,所以是错的,而map,由于其特性,利用下标会自动初始化
11.26:可以用什么类型来对一个map进行下标操作,下标运算符返回的类型是什么?请给出一个具体例子,定义一个map,然后写出一个可以用来对map进行下标操作的类型以及下标运算符将会返回的类型。
答:map键值的类型,返回类型是mapped_type对象

13.3.5节练习

11.27:对于什么问题你会使用count来解决?什么时候你又会选择find
答:要计数一般选择count,只是寻找则是find
11.28:对于一个stringintvectormap,定义并初始化一个变量来保存在其上调用find的结果
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
int main() {
	map<string, vector<int>>mp = { {"hello",{1,2,3}} };
	auto ans = mp.find("hello");
	if (ans != mp.end())cout << ans->first << " ";
	return 0;
}

11.29:如果给定的关键字不在容器中,upper_boundlower_boundequal_range会返回什么
答:指向关键字可以插入的地方
11.30:对于本节最后一个程序中的输出表达式,解释运算对象pos.first->second的含义
答:表示指向第一个查找到的关键字对应的元素的值
11.31:编写程序,定义一个作者及其作品的multimap。使用findmultimap中查找一个元素并用erase删除它。确保你的程序在元素不在map也能运行。
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
using namespace std;
int main() {
	map<string, vector<int>>mp = { {"hello",{1,2,3}} };
	multimap<string, vector<string>>mp1;
	vector<string>temp = { "hello"};
	vector<string>temp1 = { "return" };
	mp1.insert(make_pair("hello", temp));
	mp1.insert(make_pair("hello", temp1));
	auto ans = mp1.find("hello");
	if (ans != mp1.end()) {
		for (auto num : ans->second)cout << num << " ";
		mp1.erase(ans->first);
	}
	return 0;
}

11.32:使用上一题定义的multimap编写一个程序,按字典序打印作者列表和他们的作品
答:

#include<iostream>
#include<algorithm>
#include<map>
#include<unordered_map>
#include<set>
using namespace std;
int main() {
	multimap<string, vector<string>>mp1;
	vector<string>temp = { "b","a"};
	vector<string>temp1 = { "b","a" };
	mp1.insert(make_pair("li lei", temp));
	mp1.insert(make_pair("wang mei", temp1));
	multiset<string>my_set;
	for (auto num : mp1) {
		my_set.insert(num.first);
	}
	for (auto num : my_set) {
		auto temp = mp1.find(num)->second;
		sort(temp.begin(), temp.end());
		cout << num << endl;
		for (auto num : temp)cout << num << " ";
		cout << endl;
	}
	return 0;
}

11.3.6节练习

11.33:实现你自己版本的单词转换程序
答:

map<string, string>buildMap(ifstream& map_file) {
	map<string, string>trans_map;
	string key;
	string value;
	while (map_file>>key && getline(map_file, value)) {
		if (value.size() > 1)
			trans_map[key] = value.substr(1);
		else
			throw runtime_error("no rules 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.end())return map_it->second;
	else return s;
}
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 (firstword)firstword = false;
			else cout << " ";
			cout << transform(word,trans_map);
		}
		cout << endl;
	}
}

11.34:如果你将transform函数中的find替换为下标运算符,会发生什么
答:会发生意外,即便没有,下标也会直接初始化一个元素
11.35:在buildMap中,如果进行以下改写,会有什么效果

trans_map[key]=value.substr(1);
改为trans_map.insert({key,value.substr(1)});

答:``效果是一样的,但是无法覆盖新的内容

11.36:我们的程序并没有检查文件的合法性,特别是,它假定转换规则文件中的规则都是有意义的。如果文件中的某一行包含一个关键字,一个空格,然后就结束了,会发生什么。预测程序的行为并进行验证,再与你的程序进行比较。
答:会抛出错误

11.4节练习

11.37:一个无序容器与其版本相比有何优势?有序版本有何优势?
答:无序的效率通常更快,而有序则适用于需要排序的
11.38:用unordered_map重写单词计数程序和单词转换程序
答:将写过的单词计数和单词转换程序用unordered_map代替即可


版权声明:本文为qq_50271250原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。