关联容器概述
Posted xiaojianliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关联容器概述相关的知识,希望对你有一定的参考价值。
关联容器支持高效的关键字查找和访问。两个主要的关联容器:map、set。
map 中的元素是一些键-值对,关键字起到索引的作用,值表示与索引相关联的数据。
set 中每个元素都只包含一个关键字,set支持高效的关键字查询操作-----检查一个关键字是否在set中。
标准库提供了8个关联容器,8个容器间的不同体现在三个维度:
- 或者是 set 或者是 map。
- 或者要求不重复的关键字,或者允许重复的关键字。
- 按顺序保存元素或者无序保存元素。
头文件 :
map
和multimap
定义在头文件map
中。set
和multiset
定义在头文件set
中。- 无序容器则定义在
unordered_map
和unordered_set
中。
关联容器不支持顺序容器的位置相关的操作,例如 push_front
或 push_back
操作。原因是关联容器中的元素是根据关键字来存储的,这些操作对于关联容器没有意义。
关联容器也不支持构造函数或插入操作这些接收一个元素值和一个数量值的操作。
关联容器是双向的。
定义关联容器
定义关联容器:
- 定义 map 时需要指明关键字类型又需要指明值类型。
- 定义 set 时只需要指明关键字类型,因为 set 中没有值。
初始化关联容器:
- 每个关联容器都定义了一个默认的构造函数,它创建一个指定类型的空容器。
- 可以将关联容器初始化为另一个同类型的容器的拷贝。
- 可以从一个值范围来初始化关联容器,这要这些值可以转化为容器所需要的类型就可以。
- 可以对关联容器进行列表初始化。
map<string, size_t> word_count; //空容器
//列表初始化
set<string> exclude = { "the","an","a","or","and" };
map<string, string> authors = {
{"Joyce","James"},
{"Austen","Jane"},
{"Dickens","Charles"}
};
初始化 multimap 或 multiset
map
、set
中的关键字必须是唯一的,即对于一个给定的关键字,只能有一个元素等于它。multimap
、multiset
则没有此限制,它们都允许多个元素具有相同的关键字。
vector<int> ivec;
for (vector<int>::size_type i = 0; i != 10; ++i)
{
ivec.push_back(i);
ivec.push_back(i); //每个数字重复保存一次
}
set<int> iset(ivec.cbegin(), ivec.cend());
multiset<int> miset(ivec.cbegin(), ivec.cend());
cout << ivec.size() << endl; //20
cout << iset.size() << endl; //10
cout << miset.size() << endl; //20
关键字类型的要求
对于有序容器: map
、multimap
、set
、以及 multiset
关键字类型必须定义元素的比较方法,默认情况下,标准库使用关键字类型的 < 运算符来比较两个关键字。
在集合类型中,关键字就是元素的类型,在映射类型中关键字类型是元素的第一部分的类型。
有序容器的关键字类型
可以提供自定义的操作来代替关键字上的 <
运算符。所提供的操作必须在关键字类型上定义一个严格弱序,可以将严格弱序看作是小于等于。
比较函数应该具备如下性质:
- 两个关键字不能同时 小于等于对方,如果
k1
小于等于k2
,那么k2
决不能小于等于k1
。 - 如果
k1
小于等于k2
,且k2
小于等于k3
,那么k1
必须小于等于k3
。 - 如果存在两个关键字,任何一个都不小于等于另一个,那么称这两个关键字是等价的,如果
k1
等价于k2
,且k2
等价于k3
,那么k1
必须等价于k3
。
如果两个关键字是等价的, 那么容器将它们视为相等来处理,当用作 map 的关键字时,只能有一个元素与这两个关键字关联,可以使用两者中的任意一个来访问对应的值。
使用关键字类型的比较函数
用来组织一个容器中元素的操作的类型也是该容器类型的一部分。为了指定使用自定义的操作,必须在定义关联容器时提供此类型的操作。
bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs)
{
return lhs.isbn < rhs.isbn;
}
multiset<Sales_data,decltype(compareIsbn)*> bookstore(compareIsbn);
使用 decltype
指出要使用一个给定的函数类型的指针时,需要加上 *
。
用 compareIsbn
来初始化 bookstore
,表示向 bookstore
中添加元素时,通过调用 compareIsbn
函数来为这些元素排序。
pair 类型
pair
标准库类型定义在头文件 utility
中。
一个 pair
保存两个数据成员,类似容器,pair
是一个用来生成特定类型的模板,当创建一个 pair
时,必须提供两个类型名,pair
数据成员将具有对应的类型,两个类型不要求一样。
pair<string,string> anon;
pair<string,size_t> word_count;
pair<string,vector> line;
pair
的默认构造函数对数据成员进行值初始化,因此:
anon
是一个包含两个空string
的pair
。word_count
的string
被初始化为空,size_t
成员则被初始化为0。line
保存了一个空的string
和一个空的vector
。
当然,也可以为每个成员提供初始化器:
pair<string,string> author{"James","Joyce"};
pair
的数据成员是 public
的,两个成员分别命名为 frist
和 second
。
创建 pair 对象的函数
想象有一个函数需要返回 pair。在新标准下可以对返回值进行列表初始化:
pairn<string,int> process(vector<string> &v)
{
if(!v.empty())
return (v.back(),v.back().size()); //列表初始化
else
return pair(string,int); //隐士构造返回值
}
在较早版本的C++中,不允许使用括号包围的初始化器来返回pair这种类型的对象,必须显示构造返回值:
if(!v.empty())
return pair<string,int> (v.back(),v.back().size());
还可以使用make_pair来生成pair对象:
if(!v.empty())
return make_pair(v.back(),v.back().size());
以上是关于关联容器概述的主要内容,如果未能解决你的问题,请参考以下文章