【C++】map和set

目录

一、容器补充

1.序列式容器与关联式容器

我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身,其元素与元素之间并没有什么关联性。

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据查找时比序列式容器效率更高 。

2.键值对

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

3.树形结构的关联式容器

根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset 。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。

二、set

1.set的介绍

1.与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。

2.set中插入元素时,只需要插入value即可,不需要构造键值对。

3.set中的元素不可以重复(因此可以使用set进行去重)。

4.使用set的迭代器遍历set中的元素,可以得到有序序列

5.set中的元素默认按照小于来比较

6.set中查找某个元素,时间复杂度为:log n

7.set中的元素不允许修改

8.set中的底层使用二叉搜索树(红黑树)来实现

2.set的使用

Compare:仿函数,set中元素的比较方式。

构造函数:

插入:

insert 重载了三种插入方法,值、迭代器位置、迭代器区间,这里演示最常用的值插入。

cpp 复制代码
void test_set1()
{
	//排序 + 去重
	//去重原理:一个值已经有了,我们就不插入了
	set<int> s;
	s.insert(3);
	s.insert(2);
	s.insert(4);
	s.insert(5);
	s.insert(1);
	s.insert(1);
	s.insert(5);

	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

从插入数据我们可以看出,set的功能大致就是将插入的数据进行排序 + 去重,去重的原理是已经存在的值不需要再插入。

删除:

erase 也重载了三种方法:

① 删除迭代器位置(必须要求迭代器有效,一般配合find使用)、

② 删除值(有这个值就删除,没有也不会报错,底层其实就是封装了迭代器删除的过程,返回值为删除元素个数)、

③ 删除迭代器区间。

cpp 复制代码
void test_set1()
{
	//排序 + 去重
	//去重原理:一个值已经有了,我们就不插入了
	set<int> s;
	s.insert(3);
	s.insert(2);
	s.insert(4);
	s.insert(5);
	s.insert(1);
	s.insert(1);
	s.insert(5);

	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;


	s.erase(s.begin());  //删除第一个元素 迭代器位置删除
	it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	s.erase(5);      //删除值为5的位置的元素
	it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	//删除全部
	s.erase(s.begin(), s.end());
	it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

3.multset的介绍

1.multiset中在底层中存储的是<value, value>的键值对

2.mtltiset的插入接口中只需要插入即可

3,与set的区别是,multiset中的元素可以重复,set是中value是唯一的

4.使用迭代器对multiset中的元素进行遍历,可以得到有序的序列

5.multiset中的元素不能修改

6.在multiset中找某个元素,时间复杂度为: log n

7.multiset的作用:可以对元素进行排序

4.multset的使用

multiset的使用与set几乎一摸一样,唯一不同就是multiset中允许插入重复值。

count函数,返回容器中当前值的相同值的个数

equal_range函数 - 用来删除数据

erase函数

删除所有的4,并返回删除个数

三、map

1.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通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))

7.map不支持修改Key,支持修改Value。

2.map的使用

key: 键值对中key的类型

T: 键值对中value的类型

Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

map 在使用使用上的最大区别就是多了一个模板参数V(文档中给的是T),且使用时是将KV两个模板参数封装在了pair里面。

pair的第一个参数(first)是K,第二个参数(second)是V。

插入

insert函数,参数是一个value_type ,而value_type是一个pair对象,也就是我们前面说的键值对。
insert的返回值 两种情况
1.key已经在树里面,返回pair<书里面可以所在节点的iterator,flase>
2.key不在树中,返回pair<新插入key所在节点的iterator,true>
>  
插入数据可以有三种方法,键值对插入,匿名对象插入,库函数make_pair,以及多参数隐式类型转换(C++11)

删除:

可以通过某个位置的迭代器删除,也可以通过pair中first删除,也可以通过迭代器区间删除。

operator[]

所以运算符重载[],有三个作用,进行查找,插入操作,修改操作。

3.multimap的介绍

其特性与map基本一致,只是multimap中可以允许存在重复的key值

4.multimap的使用

插入

返回值和map不同,因为multimap允许插入重复值,插入数据后返回插入元素的迭代器


相关推荐
FIN技术铺几秒前
问:数据库的六种锁机制实践总结?
数据库·sql·oracle
chordful11 分钟前
Leetcode热题100-32 最长有效括号
c++·算法·leetcode·动态规划
材料苦逼不会梦到计算机白富美22 分钟前
线性DP 区间DP C++
开发语言·c++·动态规划
java小吕布23 分钟前
Java Lambda表达式详解:函数式编程的简洁之道
java·开发语言
sukalot27 分钟前
windows C#-查询表达式基础(一)
开发语言·c#
程序员劝退师_30 分钟前
优惠券秒杀的背后原理
java·数据库
Gauss松鼠会32 分钟前
GaussDB全密态数据库等值查询
数据库·oracle·gaussdb
JSUITDLWXL34 分钟前
在Oracle数据中更新整个对象和更新对象的某几个字段时,他们的锁是相同的吗
数据库·oracle
杏花春雨江南35 分钟前
ddl/dml/dcl
数据库·oracle
ahadee38 分钟前
蓝桥杯每日真题 - 第12天
c++·vscode·算法·蓝桥杯