STL-关联式容器 map

写在前面:

关联容器(Associative containers) [əˈsəʊʃiətɪv]


标准库容器类型:
1、顺序容器
比如:vector、list、deque、forward_list(C++11)等。
2、关联容器
关联式容器也是用来存储数据的,与顺序容器不同的是,其里面存储的是
结构的键值对,在 数据检索时比序列式(也就是顺序)容器效率更高。

两者之间的差别: 关联容器通过键(key)存储和读取元素顺序容器则通过元素在容器中的位置存储和访问元素且关联式容器大部分和顺序容器相同 比较特别的地方就是关联容器支持键的使用

键值对
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值, value表示与key对应的信息

关联容器共享大部分顺序容器的操作 但是关联容器不提供

front、push_front、pop_front、back、push_back 以及pop_pack操作

关联容器可以支持

begin、end、rbegin、rend操作

同时关联容器还有以下和顺序容器公共的构造函数

C c;//创建一个空的容器
C c1(c2);//用c2来拷贝构造c1 ,前提是c2必须和c1的类型相同
C c(b,e);//将序列中的元素复制到c中 b和e是表示序列的迭代器


关联容器支持通过键来高效地查找和读取元素 两个基本的关联容器的类型是

map set

map 的元素以 键 – 值 (key --value) 对的形式组织, 键用在map中的索引 而值表示所存储和读取的数据

set 仅包含一个值 并有效的支持某个值是否存在的查询

注:
如果希望有效的存储不同值的集合 那么使用set容器比较合适
map容器则更使用于需要存储、修改 每个键所关联的值的情况
比如说map可以用来实现一个简单的字典
map 和set 类型的对象所包含的元素都具有不同的键值 不允许为同一个键 添加第二个元素 也就是一个key 不能对应两个不同的value

如果一个键必须对应多个实例 则需要使用multimpmultiset
multimap :支持同一个键多次出现的map类型
multiset :支持同一个键多次出现的set类型

关联容器也支持很多顺序容器也提供相同的操作 此外 还提供 管理或只用键的特殊操作

map 关联数组 元素通过键来存取和读取
set 大小可变的集合,支持通过键实现的快速读取
multimap 支持同一个键多次出现的map类型
multiset 支持同一个键多次出席那的set类型


这次的博客主要来整理map的相关知识要点!

1. 头文件

2. map:

1.map是关联容器它按照特定的次序(按照key来比较)存储由键–key和值–value组合而成的元素。 (有序)
2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值 key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起, 为其取别名称为pair: typedef pair value_type;
3.在内部,map中的元素总是按照键值key进行比较排序的。
4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行 直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
5.map支持下标访问符,即在[ ]中放入key,就可以找到与key对应的value
6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。
注意:
关于 pair 对象就不再这里重复的介绍了,稍微的提一下
pair 也是一种类模板 ,这个类将一对值耦合在一起,这些值可能是不同类型的 ,单个值可以通过其公共成员 first 和 second 访问。
因此这里说的 key 和 value 也就是 pair 对象中的 公共成员 first 和 second

3. map类型

脑子里记住这个不是地图了哟!
map 是 "键–值对"的集合
map类型通常可理解为关联数组
可使用 "键"作为下标来获取一个值,正如内置数组类型一样 而关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。

4.模板参数

STL-关联式容器 map_第1张图片

key: 键值对中key的类型
T: 键值对中value的类型
Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照 less (小于)来比较,一般情况 下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则 (一般情况下按照函数指针或者仿函数来传递)
Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器 注意:在使用map时,需要包含头文件。

5. 容器属性

STL-关联式容器 map_第2张图片

关联容器中的元素由它们的key作为引用而不是他们在容器中的绝对位置
容器中所有的元素总是有着严格的顺序,所有插入的元素都按此顺序都有确定的位置
容器中的任何两个元素都不能具有等效的key. 也就是key不能相同

6. map对象的定义

要使用 map 对象,则必须包含 map 头文件。在定义 map 对象时,必须分 别指明"键"和"值"的类型(value type)
例如 :定义键和值都是string 类型的 map对象。

#include
#include
int main()
{
    map<string,string> m;//键索引是 string 类型的 关联的值是 string 类型的
	return 0;
}

7. map的构造函数

________________________________函数声明 __________________________说明
mapm; 创建一个名为 m 的空 map 对象,其键和值的类型分别为 k 和 v
map m(m2); 创建 m2 的副本 m也就是用m2来拷贝构造m,m 与 m2 必须有相同的键类型和值类型
map m(b, e); 使用存储迭代器 b 和 e 标记的范围内所有 元素的副本来创建m。元素的类型必须能转换为 pair

示例:

void Test1()
{
	map<string,string>m;//创建一个空的map对象 
	m.insert(pair<string,string>("helloworld!","你好世界!"));
	//插入数据
	map<string, string> m1(m);//拷贝构造
	map<string, string> m2(m.begin(), m.end());//使用迭代器进行构造
	for (auto e : m)
	{
		cout << e.first << " " << e.second << endl;
	}
	for (auto e : m1)
	{
		cout << e.first << " " << e.second << endl;
	}	for (auto e : m2)
	{
		cout << e.first << " " << e.second << endl;
	}
}

STL-关联式容器 map_第3张图片

8. map的迭代器

函数声明 功能简介

iterator begin () 返回第一个元素的位置
iterator end () 返回最后一个元素的下一个位置
const_iterator begin () const 返回第一个元素的const迭代器
const_iterator end () const 返回最后一个元素下一个位置的const迭代器
reverse_iterator rbegin() 返回第一个元素位置的反向迭代器即rend
reverse_iterator rend() 返回最后一个元素下一个位置的反向迭代器即 rbegin
const_reverse_iterator rbegin() const 返回第一个元素位置的const反向迭代器即rend
const_reverse_iterator rend() const 返回最后一元素下一个位置的反向迭代器即rbegin

大家会发现其实这个和我们之前的vector的迭代器没有多大的差别不过就是多了一个 const 的反向迭代器,用法和vector是差不多的。

做几个简单的示例:假设map对象里的值,我们事先是已经插入好了的。

	map<int, string>m;
	m.insert(pair<int, string>(1001, "小明"));
	m.insert(pair<int, string>(1003, "小红"));
	m.insert(pair<int, string>(1002, "小花"));
	m.insert(pair<int, string>(1000, "小花"));
	Test2(m);
普通正向迭代器遍历修改
	cout << "普通正向迭代器遍历" << endl;
	map<int, string>::iterator mite = m1.begin();
	while (mite != m1.end())
	{
		cout << mite->first << " " << mite->second << endl;
		++mite;
	}

在这里插入图片描述

注意:
这里再对map对象的 first 和 second 访问是使用的是 " - >" --箭头操作符
这里大家会发现map里面的是已经排好序了的,会默认把键值小的排在前面,是一个升序的排列,相对于int类型的值就会直接进行比较而 string 类型或者别的是按ASCCI码来比较如以下:
STL-关联式容器 map_第4张图片

普通反向迭代器遍历修改
	cout << "普通反向迭代器遍历" << endl;
	map<int, string>::reverse_iterator rmite = m1.rbegin();
	while (rmite != m1.rend())
	{
		rmite->second = "李飞";
		cout << rmite->first << " " << rmite->second << endl;
		++rmite;
	}

在这里插入图片描述

const 正向迭代器遍历
	cout << "const迭代器遍历" << endl;
	map<int, string>::const_iterator cite = m1.begin();
	while (cite != m1.end())
	{
		cout << cite->first << " " << cite->second << endl;
		++cite;
	}

在这里插入图片描述

const反向迭代器遍历
	cout << "const反向迭代器遍历" << endl;
	map<int, string>::const_reverse_iterator crite = m1.rbegin();
	while (crite != m1.rend())
	{
		cout << crite->first << " " << crite->second << endl;
		++crite;
	}

STL-关联式容器 map_第5张图片

范围for 与 auto 关键字遍历(推荐使用)

其实这样遍历还是比较麻烦的,相比有两种比较简约而又方便的遍历方式推荐给大家,但是他们的底层还是使用的相关迭代器进行实现的

范围 for 遍历
void Test4(map<int,string> &m)
{
	cout << "范围 for遍历" << endl;
	for (auto e : m)
	{
		cout << e.first << " " << e.second << endl;
	}
}

STL-关联式容器 map_第6张图片

auto 自动识别迭代器遍历
void Test5(map<int, string> &m)
{
	cout << "auto关键字的使用" << endl;
	auto mite = m.begin();
	while (mite != m.end())
	{
		cout <<mite->first << " " << mite->second << endl;
		++mite;
	}
}

STL-关联式容器 map_第7张图片

9. map 对象中元素的修改

函数声明 功能简介
pair insert ( const value_type& x ) 在map中插入键值对x,注意x是一个键值对,返回 值也是键值对:iterator代表新插入元素的位置, bool代表释放插入成功
iterator insert ( iterator position, const value_type& x ) 在position位置插入值为x的键值对,返回该键值对 在map中的位置,注意:元素不一定必须插在 position位置,该位置只是一个参考
template void insert ( InputIterator first, InputIterator last ) 在map中插入[first, last)区间中的元素
void erase ( iterator position ) 删除position位置上的元素
size_type erase ( const key_type& x ) 删除键值为x的元素
void erase ( iterator first, iterator last ) 删除[first, last)区间中的元素
void swap ( map& mp ) 交换两个map中的元素
void clear ( ) 将map中的元素清空 iterator find ( const key_type& x )
const_iterator find ( const key_type& x ) const 在map中插入key为x的元素,找到返回该元素的位 置的const迭代器,否则返回cend
size_type count ( const key_type& x ) const 返回key为x的键值在map中的个数,注意map中 key是唯一的,因此该函数的返回值要么为0,要么 为1,因此也可以用该函数来检测一个key是否在 map中
insert 插入一个数据

这里的插入肯定是插入一个 pair 对象,那么请看示例;

	map<int, string> m;
	pair<int, string> p1(2, "two");
	m.insert(pair<int, string>(1, "one"));
	m.insert(p1);
	for (auto e : m)
	{
		cout << e.first <<" "<<e.second << endl;
	}

STL-关联式容器 map_第8张图片

注意
在一个map对象中 key 的值是唯一的,是不允许插入两个相同的 key ,相同的key 所对应的value也无法插入
STL-关联式容器 map_第9张图片

erase 删除一个数据
	map<int, string>m;
	m.insert(pair<int, string>(1, "one"));
	m.insert(pair<int, string>(2, "two")); 
	m.insert(pair<int, string>(3, "three"));
	auto a = m.begin();
	m.erase(a);//删除迭代器位置的元素
	m.erase(3);//删除 key 为3的元素 即 first=3 的数据

STL-关联式容器 map_第10张图片

交换两个map对象

STL-关联式容器 map_第11张图片

10. map的大小容量以及 [ ]

函数声明 功能简介
bool empty ( ) const 检测map中的元素是否为空,是返回true,否则 返回false
size_type size() const 返回map中有效元素的个数
mapped_type& operator[] (const key_type& k) 返回去key对应的value

注意:
虽然 key 不能修改但是 value是可以修改的,也可以通过 [ key ]来访问对应的 value 或者修改:
如:
STL-关联式容器 map_第12张图片

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