c++关联容器

本文深入探讨了C++中的关联容器,包括map、multimap、set和multiset的基本概念、操作及其实现原理。关联容器不支持如push_front或push_back等顺序容器的操作,并且提供了如pair类型的键值对存储方式。文章通过实例展示了如何初始化和操作这些容器,特别强调了关键字类型的比较函数以及pair类型的使用,同时讨论了关联容器的迭代器和插入元素的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

关联容器都不支持顺序容器的位置相关的操作,例如push_front或push_back。而且,关联容器也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作。

map

类似顺序容器,关联容器也是模板。为了定义一个map,我们必须指定关键字和值的类型。当从map中提取一个元素时,会得到一个pair类型的对象。简单来说,pair是一个模板类型,保存两个名为first和second的数据成员,map所使用的的pair用first成员保存关键字,second成员保存对应的值。关联容器的迭代器都是双向的。

定义关联容器

可以构造空容器,也可以拷贝构造,在新标准下可以对关联容器进行值初始化。例如:

set<string>exclude={"the","but"};
map<string, string>authors = { {"joyce","james"},{"Austen","jane"} };

multimap和multiset

map或者set中的关键字必须是唯一的,但是容器multimap和multiset就没有限制,他们都允许多个元素具有相同的关键字。例如:

vector<int>v1;
	for (vector<int>::size_type i = 0; i < 10; ++i)
	{
		v1.push_back(i);
		v1.push_back(i);
	}
	cout << v1.size();
	set<int>s1(v1.begin(), v1.end());
	multiset<int>m2(v1.begin(), v1.end());
	cout << s1.size() <<" "<< m2.size();

会输出20 10 20;

使用关键字类型的比较函数

用尖括号指出要定义哪种类型的容器,自定义操作类型必须在尖括号中紧跟着元素类型给出。
例如:

class number
{
	int a;
	int b;
};
int main()
{
	multiset<number>s1;
	number one;
	s1.insert(one);
}

这样就会报错。
比较操作类型是函数指针类型;例如

class number
{
public:
	int a = 1;
	int b = 2;
};
bool compare(const number& one, const number& two)
{
	return one.a >= two.b;
}
int main()
{
	multiset<number,decltype(compare)*>s1(compare);
	number one;
	one.a = 3;
	one.b = 4;
	s1.insert(one);
	number two;
	s1.insert(two);
	for (auto num : s1)
	{
		cout << num.a << " " << num.b;
		break;
	}
}

这表示从compare来初始化s1对象,通过调用compare来为这些元素排序。

pair类型

pair在头文件utility中,pair是一个用来生成特定类型的模板,下面是创建pair:

pair<string,string>anon;
pair<string,size_t>word_count;

pari的默认构造函数对数据成员进行初始化。因此anon是一个包含两个空string的pair,我们也可以对每个成员提供初始化器:

pair<string,stirng>

与其他标准库类型不同,pair的数据成员是public的,两个成员分别命名为first和second.
pair上的操作

pair<T1,T2>p;
pair<T1,T2>p(v1,v2)///p是一个pair,first和second成员分别用v1和v2进行初始化。
make_pair<v1,v2)   ///返回一个用v1和v2初始化的pair。pair的类型从v1和v2推断出来。

创建pair对象的函数

例如:

pair<string, int>process(vector<string>& v)
{
	if (!v.empty())
	{
		return { v.back(),v.back().size() }; ///列表初始化
	}
	else
	{
		return pair<string, int>();
	}
}

我们还可以使用make_pair来生成pair对象,例如:

return make_pair(v.back(),v.back().size());

初始化列表

例如:

vector<string>process()
{
	string expected;
	string actual;
	if (expected.empty())
	{
		return {};
	}
	else if (expected == actual)
	{
		return { "functionx","okey" };
	}
	else
	{
		return { "functionX",expected,actual };
	}
}

关联容器操作

关联容器额外的类型别名:

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

由于我们不能改变一个元素的关键字,因此这些pair的关键字部分是const的:

set<string>::value_type v1;   string
set<string>key_type v2;   string
map<string,int>::value_type v3;   pair<const string,int>
map<string,int>::key_type v4;   string
map<string,int>::mapped_type v5;  int

和顺序容器一样,我们使用作用域运算符来提取一个类型的成员—例如,map<string,int>::key_type;

关联容器迭代器

必须记住,一个map的value_type是一个pair,我们可以改变pair的值,但不能改变关键字的值。
set的迭代器是const,可以用一个set迭代器来读取元素的值,但不能修改。

遍历关联容器

和顺序容器一样。

添加元素

insert有两个版本,分别接受一对迭代器,或是一个初始化器列表。

vector<int>v1 = { 2,3,4,5,2,3,6 };
	set<int>set2;
	set2.insert(v1.cbegin(), v1.cend());
	set2.insert({ 2,34,23,4,23,4 });

向map添加元素

word_count.insert({word,1}};
word_count.insert(make_pair(word,1));
word_count.insert(pair<string,size_t>(word,1));
word_count.insert(map<string,size_t>::value_type(word,1));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值