《C++primer(第五版)》学习之路-第十一章:关联容器

 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:[email protected]


11.1 使用关联容器


1.

关联容器类型

按关键字有序保存元素

map                    关联数组,保存关键字-值对

set                      关键字即值,即只保存关键字的容器

multimap            关键字可重复出现的map

multiset              关键字可重复出现的set

无序集合

unordered_map              用哈希函数组织的map

unordered_set                用哈希函数组织的set

unordered_multimap      哈希组织的map;关键字可以重复出现

unordered_multiset        哈希组织的set;关键字可以重复出现


11.2 关联容器概述


1.关联容器都支持普通容器操作。关联容器不支持顺序容器的位置相关的操作,原因是关联容器中元素都是根据关键字存储的,这些操作对关联容器没有意义。而且,关联容器也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作。


11.3 关联容器操作


1.关联容器额外的类型别名

key_type              此容器类型的关键字类型

mapped_type      每个关键字关联的类型:只适用于map

value_type          对于set,与key_type相同,对于map,为pair<const key_type,mapped_type> 


2.关联容器insert操作

c.insert(v)

c.elmpace(args)     v是value_type类型对象;args用来构造一个元素。对于map和set,只有当元素关键字不在c中才插入(或构造)元素。函数返回一个pair,包含一个迭代器,指向具有指定关键字的元素,以及一个指示插入是否是否成功的bool值。对于multimap和multiset,总会插入(或构造)给定元素,并返回一个指向新元素的迭代器。

c.insert(b,e)           

c.insert(il)               b和e是迭代器,表示一个c::value_type类型值的范围;il是这种值的花括号列表。函数返回void。对于map和set,只插入关键字不在c中的元素。对于multimap和multiset,则会插入范围中的每个元素。

c.insert(p,v)     

c.insert(p,args)       类似insert(v)(或emplace(args)),但迭代器p作为一个提示,指出从哪里开始搜索新元素应该存储的位置。返回一个迭代器,指向具有给定关键字的元素。


3.map和unordered_map的下标操作

c[k]            返回关键字为k的元素;如果k不在c中,添加一个关键字为k的元素,对其进行值初始化

c.at[k]        访问关键字为k的元素,带参数检查;若k不在c中,抛出一个out_of_range异常


4.在一个关联容器中查找元素的操纵

lower_bound和upper_bound不适用于无序容器。

下标和at操作只适用于非const的map和unordered_map

c.find(k)                     返回一个迭代器,指向第一个关键字为k的元素,若k不在容器中,则返回尾后迭代器

c.count(k)                  返回关键字等于k的元素的数量。对于不允许重复关键字的容器,返回值永远是0和1

c.lower_bound(k)      返回一个迭代器,指向第一个关键字不小于k的元素

c.upper_bound(k)      返回一个迭代器,指向第一个关键字大于k的元素

c.equal_range(k)       返回一个迭代器pair,表示关键字等于k的元素的范围。若k不存在,pair的两个成员均等于c.end()


11.4 无序容器


1.无序容器管理操作

桶接口

c.bucket_count()                 正在使用的桶的数目

c.max_bucket_count()         容器能容纳的最多的桶的数量

c.bucket_size()                   第n个桶中有多少个元素

c.bucket(k)                          关键字为k的元素在哪个桶中

桶迭代

local_iterator                      可以用来访问桶中元素的迭代器类型

const_local_iterator           桶迭代器的const版本

c.begin(n),c.end(n)            桶n的首元素迭代器和尾后迭代器

c.cbegin(n),c.cend(n)        与前两个函数类似,但返回const_local_iterator

哈希策略

c.load_factor()                    每个桶的平均元素数量,返回float值

c.max_load_factor()            c试图维护的平均桶大小,返回float值。c会在需要时添加新的桶,以使得load_factor<=max_load_factor

c.rehash(n)                        重组存储,使得bucket_count>=n且bucket_count>size/max_load_factor

c.reserve(n)                       重组存储,使得c可以保存n个元素且不必rehash


PS:部分练习答案


练习11.3

#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <cctype>

void word_count()
{
	std::map<std::string,std::size_t> cnt;
	std::string word;
	while(std::cin >> word)
		++cnt[word];
	for(const auto& elem: cnt)
		std::cout << elem.first << " : " << elem.second << std::endl;
}

int main()
{
	word_count();
	return 0;
}

练习11.4

#include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include <cctype>

void word_count_pro()
{
	std::map<std::string,int> m;
	std::string word;
	while(std::cin >> word)
	{
		for(auto& ch: word)
			ch = tolower(ch);
		word.erase(std::remove_if(word.begin(),word.end(),ispunct),word.end());
		++m[word];
	}
	for(const auto& elem:m)
		std::cout << elem.first << " : " << elem.second << std::endl;
}

int main()
{
	word_count_pro();
	return 0;
}

练习11.7

#include <iostream>
#include <map>
#include <string>
#include <algorithm>

int main()
{
	std::map<std::string, std::vector<std::string>> famls;

	std::string lastName, chldName;

	while ([&]() -> bool
{
	std::cout << "Please enter last name:\n";

	return std::cin >> lastName && lastName != "@q";
}())

	{
		std::cout << "Please enter children's name:\n";
		while (std::cin >> chldName && chldName != "@q")
		{
			famls[lastName].push_back(chldName);
		}
	}

	for (auto e : famls)
	{
		std::cout << e.first << ":\n";
		for (auto c : e.second) std::cout << c << " ";
		std::cout << "\n";
	}

	return 0;
}

练习11.8

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

int main()
{
	std::vector<std::string> exclude = {"aa", "bb", "cc"};
	for (std::string word; std::cin >> word;)
	{
		if (std::find(exclude.begin(), exclude.end(), word) != exclude.end())
			std::cout << "Already in!" << std::endl;
		else
			exclude.push_back(word);
	}
	for (auto const& s : exclude) std::cout << s << " ";
	std::cout << std::endl;
}

练习11.12

#include <vector>
#include <utility>
#include <string>
#include <iostream>

int main()
{
	std::vector<std::pair<std::string, int>> vec;
	std::string str;
	int i;
	while (std::cin >> str >> i)
		vec.push_back(std::pair<std::string, int>(str, i));
	for (const auto& p : vec)
		std::cout << p.first << ":" << p.second << std::endl;
}

练习11.14

#include <iostream>
#include <map>
#include <string>
#include <vector>

using std::ostream;
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::make_pair;
using std::pair;
using std::vector;
using std::map;

class Families
{
	public:
		using Child = pair<string,string>;
		using Children = vector<Child>;
		using Data = map<string,Children>;
		
		void add(string const& last_name,string const& first_name,string birthday)
		{
			_data[last_name].push_back(make_pair(first_name,birthday));
		}
		ostream& print(std::ostream& os) const
		{
			if(_data.empty())
			return os << "No data right now." << endl;
			for(const auto& pair:_data)
			{
				os << pair.first << endl;
				for(const auto& child : pair.second)
				os << child.first << " " << child.second << endl;
				os << endl;
			}
			return os;
		}
	private:
		Data _data;
};

int main()
{
	Families families;
	string message = "Please enter last name, first name and birthday";
	for(string l,f,b;cout << message << endl,cin>>l>>f>>b;families.add(l,f,b));
	families.print(cout << "Current data:" << endl);
}

练习11.16

std::map<int, std::string> map;
map[25] = "Alan";
std::map<int, std::string>::iterator it = map.begin();
it->second = "Wang";

练习11.18

#include <iostream>
#include <map>
#include <string>

int main()
{
	std::map<std::string, size_t> word_count{{"123",1},{"456",2}};
	std::map<std::string, size_t>::const_iterator map_it = word_count.cbegin();
	while (map_it != word_count.cend())
	{
		std::cout << map_it->first << " occurs " << map_it->second << " times" << std::endl;
		++map_it;
	}

	return 0;
}

练习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 <map>
#include <string>

using std::string;

int main()
{
	std::map<string,size_t> word_count;
	string word;
	while(std::cin >> word)
	{
		auto ret = word_count.insert({word,1});
		if(!ret.second)
			++ret.first->second;
	}
	for(const auto& elem: word_count)
		std::cout << elem.first << " " << elem.second << ((elem.second>1)?"times":"time") << std::endl;
}

练习11.23

#include <iostream>
#include <map>
#include <string>

using std::string;

int main()
{
	std::multimap<string,string> families;
	for(string lastName,childName;std::cin>>childName>>lastName;families.emplace(lastName,childName));
	for(const auto& s:families)
	std::cout << s.second << " " << s.first << std::endl;
}

练习11.31

#include <iostream>
#include <map>
#include <string>

using std::string;

int main()
{
	std::multimap<string, string> authors
	{
		{"alan", "DMA"}, {"pezy", "LeetCode"}, {"alan", "CLRS"},
		{"wang", "FTP"}, {"pezy", "CP5"},      {"wang", "CPP-Concurrency"}
	};
	string author = "pezy";
	string work = "CP5";
	
	auto found = authors.find(author);
	auto count = authors.count(author);
	while(count)
	{
		if(found->second == work)
		{
			authors.erase(found);
			break;
		}
		++found;
		--count;
	}
	for(const auto& author : authors)
	std::cout << author.first << " " << author.second << std::endl;
}

练习11.32

#include <iostream>
#include <map>
#include <set>
#include <string>

using std::string;

int main()
{
	std::multimap<string, string> authors
	{
		{"alan", "DMA"}, {"pezy", "LeetCode"}, {"alan", "CLRS"},
		{"wang", "FTP"}, {"pezy", "CP5"},      {"wang", "CPP-Concurrency"}
	};
	std::map<string,std::multiset<string>> order_authors;
	for(const auto& author : authors)
	order_authors[author.first].insert(author.second);
	for(const auto& author : order_authors)
	{
		std::cout << author.first << ": ";
		for(const auto& work: author.second)
		std::cout << work << " ";
		std::cout << std::endl;
	}
}

练习11.33

#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <sstream>

using std::string;
using std::ifstream;

std::map<string,string> buildMap(ifstream& map_file)
{
	std::map<string,string> trans_map;
	for(string key,value; map_file >> key && getline(map_file,value);)
		if(value.size()>1)
			trans_map[key] = value.substr(1).substr(0,value.find_last_not_of(' '));
	return trans_map;
}

const string& transform(const string& s,const std::map<string,string>& m)
{
	auto map_it = m.find(s);
	return map_it == m.cend()?s:map_it->second;
}

void word_transform(ifstream& map,ifstream& input)
{
	auto trans_map = buildMap(map);
	for(string text; getline(input,text);)
	{
		std::istringstream iss(text);
		for(string word; iss>>word;)
			std::cout << transform(word,trans_map) << " ";
		std::cout << std::endl;
	}
}

int main()
{
	ifstream ifs_map("word_transformation_bad.txt"),ifs_content("given_to_transform.txt");
	if(ifs_map && ifs_content)
		word_transform(ifs_map,ifs_content);
	else
		std::cerr << "can't find the documents." << std::endl;
}

练习11.38

#include <iostream>
#include <unordered_map>
#include <string>
#include <set>
#include <fstream>
#include <sstream>

using std::string;
using std::ifstream;

void wordCounting()
{
	std::unordered_map<string,size_t> word_count;
	for(string word;std::cin >> word;++word_count[word]);
	
	for(const auto& w:word_count)
	std::cout << w.first << "occurs" << w.second << (w.second>1?"times":"time") << std::endl;
}

void wordTransformation()
{
	std::ifstream ifs_map("word_transformation_bad.txt"),ifs_content("given_to_transform.txt");
	if(!ifs_map || !ifs_content)
	{
		std::cerr << "can't find the documents." << std::endl;
		return;
	}
	std::unordered_map<string,string> trans_map;
	for(string key,value; ifs_map >> key && getline(ifs_map,value);)
		if(value.size()>1)
			trans_map[key] = value.substr(1).substr(0,value.find_last_not_of(' '));

	for(string text,word; getline(ifs_content,text); std::cout << std::endl)
		for(std::istringstream iss(text); iss>>word;)
		{
			auto map_it = trans_map.find(word);
			std::cout << (map_it == trans_map.cend()?word:map_it->second) << " ";
		}
}

int main()
{
	wordTransformation();
}


你可能感兴趣的:(C++Primer)