C++ Primer 中文第 5 版练习答案 第 11 章 关联容器

C++ Primer 中文版(第 5 版)练习解答合集

自己写的解答,如有错误之处,烦请在评论区指正!


1

map 是关联型容器,vector 是顺序性容器。

map 中的元素是键值对,并且自动按照键排序

2

list:不确定数据量大小,需要频繁插入删除,很少查找

vector:不需要频繁在中间插入删除,需要频繁随机访问

deque:只在头尾插入删除,需要频繁随机访问

map:需要存放两个集合之间的映射关系

set:需要存放不重复的元素,且要能快速查找是否已存在

3

#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;

int main() {
	string buffer;
	unordered_map<string, int> word_cnt;
	while (cin >> buffer)
		++word_cnt[buffer];
	for (auto item : word_cnt)
		cout << item.first << " " << item.second << endl;
	return 0;
}

4

#include <iostream>
#include <string>
#include <cctype>
#include <set>
#include <unordered_map>
using namespace std;

int main() {
	string buffer;
	// punct will be ignored at the end of the word
	set<char> ignore{',', '.'};
	unordered_map<string, int> word_cnt;
	while (cin >> buffer) {
		for (auto& ch : buffer)
			ch = tolower(ch);
		if (buffer.size() > 1 && ignore.find(buffer[buffer.size()-1]) != ignore.end())
			buffer.erase(buffer.size()-1);
		++word_cnt[buffer];
	}
	for (auto item : word_cnt)
		cout << item.first << " " << item.second << endl;
	return 0;
}

5

map 存放键值对,set 只存放键

需要存放对应关系的时候使用 map,只需要记录关键字就用 set

6

set 是关联型容器,list 是顺序容器

set 中的元素不能重复,list 可以

list 中元素的顺序可以在插入后自行调节,但是 set 一旦事先制定了排序规则,元素插入后就不能改变位置

7

#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;

int main() {
	string family_name, kid_name;
	map<string, vector<string>> family_kids;
	while (cin >> family_name >> kid_name) {
		family_kids[family_name].push_back(kid_name);
	}
	for (const auto& item : family_kids) {
		cout << item.first << ":" << endl;
		for (const auto& name : item.second) {
			cout << name << " ";
		}
		cout << endl;
	}
	return 0;
}

8

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int main() {
	vector<string> vecSet;
	string buffer;
	while (cin >> buffer) {
		if (find(vecSet.begin(), vecSet.end(), buffer) == vecSet.end())
			vecSet.push_back(buffer);
	}
	for (auto str : vecSet)
		cout << str << " ";
	return 0;
}

set 会自动去掉重复的元素,并且寻找关键字的效率高,还会对关键字自动排序。

9

map<string, list<int>> word_pages;

10

vector 的迭代器之间支持小于运算符,而 list 的迭代器不支持。所以前者可以,后者不行(除非重载list 迭代器的小于运算符,或者给一个自定义的比较函数)。

11

multiset<Sales_data, bool (*)(const Sales_data& lhs, const Sales_data& rhs)> bookstore(cmp);

12

#include <iostream>
#include <vector>
#include <string>
#include <utility>
using namespace std;

int main() {
	vector<pair<string, int>> vec;
	int num;
	string buffer;
	while (cin >> buffer >> num) {
		vec.emplace_back(make_pair(buffer, num));
	}
	for (auto p : vec)
		cout << p.first << ": " << p.second << endl;
	return 0;
}

13

#include <iostream>
#include <vector>
#include <string>
#include <utility>
using namespace std;

int main() {
	vector<pair<string, int>> vec;
	int num;
	string buffer;
	while (cin >> buffer >> num) {
//		// version 1
//		vec.emplace_back(make_pair(buffer, num));
//		// version 2
//		vec.emplace_back(pair<string, int>{buffer, num});
		// version 3
		vec.emplace_back(pair<string, int>(buffer, num));
	}
	for (auto p : vec)
		cout << p.first << ": " << p.second << endl;
	return 0;
}

14

#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;

int main() {
	string family_name, kid_name, birth;
	map<string, vector<pair<string, string>>> family_kids;
	while (cin >> family_name >> kid_name >> birth) {
		family_kids[family_name].push_back(make_pair(kid_name, birth));
	}
	for (const auto& item : family_kids) {
		cout << item.first << ":" << endl;
		for (const auto& p : item.second) {
			cout << p.first << " " << p.second << endl;
		}
		cout << endl;
	}
	return 0;
}

15

对一个 int 到 vector<int> 的 map
mapped_type: vector<int>
key_type: const int
value_type: pair<const int, vector<int>>

16

map<int, int> int_ints;
int_ints[3] = 5;
auto it = int_ints.begin();
it->second = 10;

17

第 1、2 行非法。不能通过迭代器修改 set 中的关键字,所有迭代器都是 const_iterator

第 3、4 行合法。将 c 中所有 string 依次插入到 v 中

18

map<const string, size_t>::iterator

19

multiset<Sales_data, bool (*)(const Sales_data& lhs, const Sales_data& rhs)>::iterator it = bookstore.begin();

20

#include <iostream>
#include <string>
#include <cctype>
#include <set>
#include <unordered_map>
using namespace std;

int main() {
	string buffer;
	// punct will be ignored at the end of the word
	set<char> ignore{',', '.'};
	unordered_map<string, int> word_cnt;
	while (cin >> buffer) {
		for (auto& ch : buffer)
			ch = tolower(ch);
		if (buffer.size() > 1 && ignore.find(buffer[buffer.size()-1]) != ignore.end())
			buffer.erase(buffer.size()-1);
		auto ret = word_cnt.insert({buffer, 1});
		if (!ret.second)
			++ret.first->second;
	}
	for (auto item : word_cnt)
		cout << item.first << " " << item.second << endl;
	return 0;
}

21

如果插入失败,则把原本存在的这个 word 的值加 1

如果插入成功,则插入的这个 word 的值是 0,将其变成 1

总之,等价于原来的:

auto ret = word_cnt.insert({buffer, 1});
if (!ret.second)
    ++ret.first->second;

22

pair<map<string, vector<int>>::iterator, bool> insert(pair<const string, vector<int>>)

23

#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;

int main() {
	string family_name, kid_name;
	multimap<string, string> family_kids;
	while (cin >> family_name >> kid_name) {
		family_kids.insert({family_name, kid_name});
	}
	for (const auto& item : family_kids) {
		cout << item.first << ": "
		     << item.second << endl;
	}
	return 0;
}

24

新建一个 名为 m 的 map,是 int 类型到 int 类型的映射。

使用下标运算符寻找关键字为 0 的元素,没有找到,就将其值初始化,最后将其赋值为 1

25

对 vector 这样操作是非法的,因为 vector 现在是空的,不能用下标操作符去索引不存在的空间。

26

可以用该 map 的 key_type 类型来对 map 进行下标操作,返回的类型是 mapped_type

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main() {
	map<int, string> m;
	m[6] = "Hello";
	map<int, string>::key_type k = 6;
	cout << m[k].substr(1, 2) << endl;
	return 0;
}

27

需要明确知道关键字在关联容器中出现的次数(特别是对 multi 类型的关联容器)时,使用 count。如果只关心其是否出现,使用 find

28

map<string, vector<int>>::iterator it = m.find(target);

29

upper_bound 返回第一个安全的插入点,默认情况下是第一个大于给定关键字的位置

这种情况下,lower_bound 返回值和 upper_bound 一样

equal_range 返回一个 pair,其 first 成员和 second 成员同上

30

pos 是一个 pair 类型,其 first 成员的初始值是调用 lower_bound(search_item) 的返回值,即一个迭代器,指向第一个大于等于给定关键字的位置。而其 second 成员是调用 upper_bound(search_item) 的返回值

所以 pos.first 是一个用来遍历 lower_bound(search_item) 和 upper_bound(search_item) 范围内的迭代器,对其解引用后访问其 second 成员就得到了 map 中的值,即题目。

31

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main() {
	multimap<string, string> author_titles{
		{"Jane Austen", "Pride and Prejudice"},
		{"James Joyce", "Ulysses"},
	};
	auto it = author_titles.find("James Joyce");
	if (it != author_titles.end())
		author_titles.erase(it);
	it = author_titles.find("XXX");
	if (it != author_titles.end())
		author_titles.erase(it);
	for (auto item : author_titles)
		cout << item.first << ": " << item.second << endl;
	return 0;
}

32

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main() {
	multimap<string, string> author_titles{
		{"Jane Austen", "Pride and Prejudice"},
		{"James Joyce", "Ulysses"},
		{"XXX", "aaaaaaa"},
		{"XXX", "baaaa"},
		{"Y", "aaa"},
		{"Y", "z"},
		{"XXX", "ba"},
	};
	auto it = author_titles.begin();
	while (it != author_titles.end()) {
		auto pos = author_titles.upper_bound(it->first);
		cout << it->first << ":" << endl;
		for (; it != pos; ++it)
			cout << it->second << endl;
	}
	return 0;
}

33

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <unordered_map>
using namespace std;

int main() {
	ifstream map_file("map_file.d");
	ifstream words_file("words_file.d");
	string input1, input2;
	unordered_map<string, string> trans_map;
	while (map_file >> input1 >> input2) {
		trans_map[input1] = input2;
	}
	string line, word;
	while (getline(words_file, line)) {
		istringstream iss_line(line);
		bool firstWord = true;
		while (iss_line >> word) {
			auto it = trans_map.find(word);
			if (firstWord)
				firstWord = false;
			else
				cout << " ";
			cout << (it == trans_map.end() ? word : it->second);
		}
		cout << endl;
	}
	return 0;
}

34

如果换成下标运算符,那么查找 map 中不存在的字符串时,会自动值初始化一个键值对

35

如果输入中出现前后两个关键字相同,但是值不同的情况 ,行为就会出现差异。如果改成 insert 的写法,遇到下一个相同的关键字时,会插入失败。

结果上看,如果输入中有键值对 k, v1k, v2…… k, vn,用下标的写法最终 map 中是 k, vn,但是用 insert 的写法 map 中是 k, v1

36

我的程序依然能运行。但是会忽略输入文件的最后一行,也不会对最后一个关键字作替换。

37

无序的优势在于,当维护元素有序的代价非常高昂,或者没有必要维护有序的时候,相对来说性能更好。

有序版本可以自动维护关键字有序。

38

用 unordered_map 替换 map 即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值