C++Primer 第十一章 关联容器 习题答案

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值