11.3 关联容器操作


类型别名:

类型别名说明
key_type关键字类型,map的first或者set的元素
mapped_typemap中值类型
value_typeset为const key_type;map中为pair<const key_type,mapped_type>

关联容器迭代器

解引用一个关联迭代器,会得到类型为value_type的值引用。

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

using namespace std;

int main() 
{
	map<string, int> word_count = { {"red",1},{"green",2},{"pipi",3}};
	set<string> limit = { "the","a","an" };
	auto beg1 = word_count.begin();
	auto beg2 = limit.begin();
	cout << beg1->first << "   " << beg1->second << endl;
	beg1++;
	cout << beg1->first << "   " << beg1->second << endl;
	cout << *beg2 << endl;
	beg2++;
	cout << *beg2 << endl;
	/*输出结果:green   2
				pipi   3
				a
				an
	*/
	return 0;
}

关键字成员不可修改,值可修改

虽然set类型同时定义了iterator 和const_ iterator 类型,但两种类型都只允许只读访问set中的元素。与不能改变-一个map元素的关键字一样,一个set中的关键字也是const的。可以用- 一个set迭代器来读取元素的值,但不能修改。

关于泛型算法

一般不在关联容器中应用泛型算法,实际应用一般作为源序列或目的位置。

最多常用的泛型算法仅有find,查询不修改重排内部的值,或者copy把关联容器当作复制的对象,复制到其他相关容器中。

添加元素

向set插入元素

使用insert函数插入,插入的方式有三种,一种是插入具体元素,一种是插入一个范围,还有一种是插入一段序列。

由于set内部的数据是不重复的,就算插入重复的,对于set来说只是自动去重而已,并不是很严重。

样例:

#include<iostream>
#include<map>
#include<set>
#include<vector>

using namespace std;

int main() 
{
	vector<int> vec = { 1,1,2,2,3,4,5 };
	set<int> set1, set2,set3;
	set1.insert(vec[0]);
	set2.insert(vec.begin(), vec. end());
	set3.insert({ 1,1,2,2,3,4,5 });
	cout << "set1:";
	for (auto i : set1 )
	{
		cout << i << " ";
	}
	cout << endl<<"set2:";
	for (auto i : set2)
	{
		cout << i << " ";
	}
	cout << endl << "set3:";
	for (auto i : set3)
	{
		cout << i << " ";
	}
	return 0;
}

输出结果:
在这里插入图片描述

向map插入数据

基本上是以下的四种写法:

stu.insert({ "qq",4 });
stu.insert(make_pair("aa",5 ));
stu.insert(pair<string,int>("bb", 6));
stu.insert(map<string, int>::value_type("cc", 7));

insert操作总结

	//args代表构造出一个与c所需要的类型一致的数据。
	//插入单个值
	//对于map和set,只有关键词不在c中时,才对容器进行插入操作。返回一个pair,指向具有指定在关键字元素的迭代器和插入是否成功的bool值。
	//对于multimap和multiset,可以插入,返回指向新元素的迭代器。
	> c.insert(v)   
	> c.emplace(args)
	//p指出从哪里开始搜索新元素存储的位置。返回指向给定关键字元素的迭代器。
	> c.insert(p,v)
	> c.emplace(p,args)
//插入多个值,返回void
	> c.insert(b,e)
	> c.insert(il)

值得关注的是:
map元素再次插入即是修改其值。

#include<iostream>
#include<map>

using namespace std;

int main() 
{
	map<string, int> map1 = { {"张三",1},{"李四",2} };
	map1.insert(make_pair("张三", 2));
	cout << map1.begin()->second << endl;
	//输出结果:2
	return 0;
}

检测insert的返回值

insert ( 或emplace)返回的值依赖于容器类型和参数。对于不包含重复关键字的容器(常指map和set),添加单一元素的insert 和emplace版本返回一个pair,告诉我们插入操作是否成功。pair的first成员是一个迭代器,指向具有给定关键字的元素;:second成员是一个bool值,指出元素是插入成功还是已经存在于容器中。如果关键字已在容器中,则insert什么事情也不做,且返回值中的bool部分为false. 如果关键字不存在,元素被插入容器中,且bool值为true。

	auto j = stu.insert({ "qq",4 });
	cout << "j "<<(j.first)->first << " " << (j.first)->second<< " " << j.second << endl; //j qq 4 1
	auto k = stu.insert({ "qq",4 });
	cout << "k " << (k.first)->first << " " << (k.first)->second << " " << k.second << endl; //k qq 4 0
	//k和j的实际类型为:pair<map<string,int>::iterator,bool>

展开递增语句

计算字母出现次数:

	string s;
	cout << "input string:" << endl;
	cin >> s;
	map<char, int> lettertimes;
	for (char a : s) {
	//循环内可以修改为:++lettertimes.insert({a,0}).first->second;
		auto p = lettertimes.insert({ a, 1 });
		if (!p.second) {
			++p.first->second;
		}
	}
	for (auto i : lettertimes) {
		cout << i.first << " " << i.second << endl;
	}

++p.first->second;此句是重点,代表着实际上也就是对应字符的数字++

向multiset和multimap添加元素

以multimap为例子吧:

	multimap<string, string> vec;
	//插入第一个元素 关键字为张三
	vec.insert("张三", "李四");
	//插入第二个元素,关键字仍然为张三
	vec.insert("张三", "王五");

对允许重复关键字的容器,接受单个元素的insert操作返回一个指向新元素的迭代器。这里无须返回一个bool值,因为insert总是向这类容器中加入一个新元素。

删除元素

c.erase(k) //删除关键词为k的元素,返回size_type值,即删除元素数量,返回0表示map中没有要删除元素
c.erase(p) //删除迭代器p处元素,返回p之后元素的迭代器,或c.end()
c.erase(b,e) //删除迭代器b~e范围元素,返回e

map下标操作

map和unordered_map提供了下标运算和对应at函数,当关键字不在map中时,下标操作会为该关键字创建元素并插入到map中,关联值可以被值初始化。

只可以对非const类型map进行下标操作。

set、multimap、unordered_multimap不支持下标运算。set中没有值对应关键字。multimap、unordered_multimap存在单关键字对多值。

//访问
	cout << stu["hh"] << endl; //1
	cout << stu.at("hh") << endl; //1
//插入并进行值初始化
	stu["xh"] = 23;
	cout << stu["xh"] << endl;
	stu["hx"]; //值为0

对于顺序容器,解引用和下标运算返回类型一样。而对于map,下标操作返回mapped_type类型(返回的是值),而迭代器运算符返回的是value_type类型(关键字-值对)。

访问元素

//不需要计数时使用find。需要计数使用count
c.find(k)  //返回指向第一个关键字k元素的迭代器。k不在容器中时返回尾后迭代器
c.count(k) //返回关键字k数量
c.equal_range(k) //对于multimap和multiset,同关键字元素会相邻储存,通过此函数查找,返回迭代器pair,表示关键词等于k的元素范围。k不存在时,返回{c.end(),c.end()}。

//不适用于无序容器
c.lower_bound(k) //返回指向第一个不小于关键字k的元素的迭代器,指向第一个k
c.upper_bound(k) //返回指向第一个大于关键字k的元素的迭代器,指向最后一个k

小总结:

  1. 在不需要创建新的map的时候,使用find代替下标操作,因为下标操作的时候,不存在他会进行创建,造成不必要的麻烦。
  2. c.equal_range(k)一般可以应用于:查找某一作者(关键字)的数目(值)。查找班级中姓李(关键字)的人名(值)等。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值