C++中的关联容器

1.关联容器类型

有序容器使用比较函数来比较关键字,从而将元素按顺序存储。默认情况下,比较操作是采用关键字类型的<运算符。无序容器使用关键字类型的==运算符和一个hash<key_type>类型的对象来组织元素。

<1>按关键字有序保存

map关联数组;保存关键字-值对
set关键字即值,即只保存关键字的容器
multimap关键字可重复出现的map
multiset关键字可重复出现的set
<2>无序集合

unordered_map 用哈希函数组织的map
unordered_set 用哈希函数组织的set
unordered_multimp 哈希组织的map;关键字可以重复出现
unordered_multiset       哈希组织的set;关键字可以重复出现
<3>map和set混用实例

int main()
{
	map<string, size_t> word_count;
	set<string> exclude = { "am","is","my"};
	string word;
	while (cin >> word)
		if (exclude.find(word) == exclude.end())//只统计不在exclude中的单词
			++word_count[word];//如果word还未在map中,下标运算符会创建一个新元素
	for (auto w : word_count)
		cout << w.first << " occurs " << w.second <<((w.second>1)?" times ":" time ")<< endl;
	system("pause");
	return 0;
}
2.pair类型

<1>一个pair保存两个数据成员。类似容器,pair是一个用来生成特定类型的模板。定义在头文件utility中。

pair<string, int> p1;
pair<string, string> p2{ "wang","kai" };
3.关联容器操作

<1>

key_type容器类型的关键字类型
mapped_type每个关键字关联的类型;只适用于map
value_type对于map,为pair<const key_type,mapped_type>
对于set,与key_type相同

int main()
{
	set<string>::value_type v1;//v1是一个string
	map<string, int>::key_type v2;//v2是一个string
	map<string, int>::mapped_type v3;//v3是一个int
	map<string, int>::value_type v4;//v4是一个pair<const string,int>
	system("pause");
	return 0;
}
<2>关联容器迭代器

当解引用一个关联容器迭代器时,我们会得到一个类型为容器的value_type的值的引用。注意:不能改变关键字成员的值。

int main()
{
	map<int, string> m{ {1,"wang"},{2,"li"},{3,"zhao"} };
	auto map_it = m.begin();
	map_it->first = 5;//错误。“map_it”: 不能给常量赋值
	map_it->second = "yan";//正确
	system("pause");
	return 0;
}
set的迭代器是const的,所以可以用一个set迭代器来读取元素的值,但不能修改。

int main()
{
	set<int> s = {1,2,3,4,5};
	set<int>::iterator set_it = s.begin();
	*set_it = 6;//错误。“set_it”: 不能给常量赋值
	system("pause");
	return 0;
}
4.向关联容器中添加元素

<1>要注意的是,map中元素的类型是pair。

int main()
{
	map<string, int> word_count;
	word_count.insert(make_pair("wang",1));
	word_count.insert({ "yan",2 });
	word_count.insert(pair<string, int>("rong", 3));
	system("pause");
	return 0;
}
<2>insert返回的值依赖于容器类型和参数。对于不包含关键字的容器,添加单一元素的insert和emplace版本返回一个pair。pair的first成员是一个迭代器,指向具有给定关键字的元素;second成员是一个bool值,指出元素是插入成功还是已经存在于容器中。如果关键字已经存在于容器中,则insert什么事情也不做,返回值的bool部分为false。如果关键字不存在,元素被插入到容器中,且bool值为true。

理解下面代码(C++ PrimerP385页):

int main()
{
	string word;
	map<string, size_t> word_count;
	while (cin >> word)
	{
		auto ret = word_count.insert({ word,1 });
		if (!ret.second)
			++ret.first->second;
	}
	system("pause");
	return 0;
}

<3>向multiset或multimap中添加元素时,insert总会插入一个元素。此时,insert操作返回一个指向新元素的迭代器,指向这个新插入的元素。


5.向关联容器中删除元素

c.erase(k)  从c中删除每个关键字为k的元素。返回一个size_type值。指出删除元素的数量。
c.erase(p)  从c中删除迭代器p指定的元素。p必须指向c中一个真实元素,不能等于c.end()。返回一个指向p之后元素的迭代器。若p指向c中的尾元素,则返回c.end()

c.erase(b,e)                                            
删除迭代器对b和e所表示的范围中的元素。返回e
6.map的下标操作

map和unordered_map容器提供了下标运算符和一个对应的at函数。注意set类型不支持下标运算符,因为没有于关键字相关联的值。同时,也不能对一个multimap或一个unordered_multimap进行下标操作,因为这两个容器可能有多个值与一个关键字相对应。

map的下标运算与以前其它下标运算的不同之处是返回类型。一般来说,解引用一个迭代器返回的类型与下标运算符返回的类型是一样的。但在map中,当对map进行下标操作时,会得到一个value_type对象(值),但当解引用一个map迭代器时,会得到value_type对象(pair)。此外,若关键字还未在map中,下标运算符会添加一个新元素。

7.访问元素

<1>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()
<2>对map使用find代替下标操作

下标操作的副作用是有时我们只想知道一个元素是否在map中,但利用下标操作使得元素不存在时会自动添加。所以只查看时可以借助上表中的方法。

<3>应用举例

int main()
{
	string search_item("yan rong");//要查找的作者名称
	auto entries = authors.count(search_item);//作品数量
	auto iter = autors.find(search_item);//作者的第一本书
	while (entries)
	{
		cout << iter->second << endl;//打印找到的书名
		++iter;//符合条件的下一本书
		--entries;
	}
	system("pause");
	return 0;
}


int main()
{
	string search_item("yan rong");
	for (auto pos = authors.equal_range(search_item); pos.first != pos.second; ++pos.first)//pos中保存的是迭代器,表示与关键字匹配的元素范围
		cout << pos.first->second << endl;
	system("pause");
	return 0;
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值