C++set和map详细介绍

这篇具有很好参考价值的文章主要介绍了C++set和map详细介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

在本篇文章中,我们将会学到关联式容器set,multiset,map,multimap。
其中前两种容器对应我们上篇二叉树文章中的K模型,后两者容器对应我们的KV模型。
我们来详细看一下吧!!!

一、关联式容器和序列式容器

我们在之前学习到的vector,list,stack,queue等都属于序列式容器,底层是线性结构,只存储数据。
关联式容器也是也是用来存储数据的,不过存储的是<K,V>这样一个键值对。

二者有什么区别呢??
⭐️序列式容器中仅仅存储一个值,关联式容器中存储一个键值对
⭐️序列式容器内部不涉及排序,关联式容器内部自动排序
⭐️序列式容器的查找按照自身的值进行相关查找,关联式容器根据K的值进行查找。
并且关联式速度比序列式容器查找快很多。

键值对

键值对是由<K,V>两个值构成的,其中K叫做键值,V就是与之对应的数据。
比如在日常生活中我们用到的英汉字典,就是一个键值对,每个英文单词对应一个中文翻译。英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。

在C++中STL中已经帮助我们实现了键值对---->(pair)

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
T1和T2可以是两个不同的类型,访问是值是first,第二个值是second。

二、set

1.set文档介绍

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

看一下模板参数

🌟T:底层存储的数据类型
🌟Compare:比较方式,默认按照小于方式比较
🌟Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

set文档介绍

  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
  5. set在底层是用二叉搜索树(红黑树)实现的。

看一下要点:
⭐️⭐️ set底层是一颗二叉树,内容可以删除,但不允许修改,查找某个元素时间复杂度为logN。
⭐️⭐️ set中不允许出现重复元素,本质是排序+去重
⭐️⭐️ set的迭代器遍历是一个有序序列
⭐️⭐️ set存的是一个值value,但是在底层也是一个键值对,不过这个键值对两个值都相同,即<value,value>,我们在使用时,只需要插入就可以,不需要构建键值对。
⭐️⭐️set比较默认按照小于比较
⭐️⭐️对于unique算法,去重相邻重复元素,去重之前需要先排序,才可以达到去重的效果。并不会改变容器的大小,随后调用erase删除这些重复元素。
nums.erase(unique(nums.begin(), nums.end()), nums.end());

2.set成员函数

1.构造函数

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
🌟🌟空的set

set< int >s;

🌟🌟迭代器区间构造set

set< int >s(s2.begin(),s2.end());

🌟🌟拷贝构造set

set< int >s(s2);

2.迭代器

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

遍历

🌟🌟迭代器遍历

set<int>s;
int a[] = { 8, 3, 1,1,2,3,4,5,6,7,10, 6, 4, 7, 14, 13 };
for (auto& e : a)
{
	s.insert(e);
}
//迭代器遍历
set<int>::iterator it = s.begin();
while (it != s.end())
{
	cout << *it << " ";
	it++;
}
cout << endl;

我们可以看到确实完成了去重任务。
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

🌟🌟范围for

	for (auto& e : s)
	{
		cout << e << " ";
	}

3.容量

🌟 🌟 empty
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
判断set是否为空

🌟 🌟 size
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
找出set中有效元素的个数。

4.修改

🌟 🌟insert
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

第一个:直接插入一个值
第二个:在某个位置插入一个值
第三个:插入一个迭代器区间

看起来很简单蛮,我们来看点诡异的,第一个的返回值
pair<iterator,bool> 返回一个键值对??

我们看一下文档的介绍
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
如果插入成功就返回插入结点的迭代器,并且返回true。
如果插入失败,也就是set中有这个元素,返回set中这个元素的迭代器,返回false。

🌟 🌟erase
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

第一个删除某个迭代器位置的值
第二个删除这个值,注意这个返回值,返回set中val这个元素的个数。
第三个删除一段迭代器区间

第一个删除和第二个删除有什么不同呢??

看一下这段代码,运行结果是什么??

	set<int>s;//空的set
	int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
	for (auto& e : a)
	{
		s.insert(e);
	}
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	//查找删除
	set<int>::iterator pos = s.find(3);
	s.erase(pos);
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
成功的把3删除了,那我们如果删除一个不存在的值呢???

	pos = s.find(30);
	s.erase(pos);
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
系统直接崩溃了,所以我们需要加判断!!!
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
那如果用第二种方法直接删除一个不存在的值呢??

s.erase(20);

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
我们发现并没有报错。

对于直接删除:在就删除,不在不做任何处理

我们要注意这两个的区别!!!!

🌟 🌟swap
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
交换两个set的值
🌟 🌟clear
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
清空set中的元素

5.其他

🌟 🌟find
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
查找某个值,如果存在返回对应的迭代器区间,不存在返回end的迭代器。
🌟 🌟countC++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
记录val这个值的个数,在set中出现了多少次。返回set中值为x的元素的个数

🌟 🌟lower_bound
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
记录大于等于val的迭代器
如果这个值存在,返回这个值的迭代器。
如果这个值不存在,返回大于这个值的迭代器。

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
在set中存在3,解引用就返回3。查找9,9不存在,就返回下一个

🌟 🌟upper_bound
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
upper_bound也是同样的道理,但是不同的是,这个返回大于val的迭代器。C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

三.multiset

multiset本质和set没有太大差别

我们先来看一下文档
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
  2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成
    的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器
    中进行修改(因为元素总是const的),但可以从容器中插入或删除。
  3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则
    进行排序。
  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭
    代器遍历时会得到一个有序序列。
  5. multiset底层结构为二叉搜索树(红黑树)

与set相比,不同的是,multiset允许重复的值存在,本质就是排序。其他的都与set相同。

	set<int>s;
	int a[] = { 8, 3, 1,1,2,3,4,5,6,7,10, 6, 4, 7, 14, 13 };
	for (auto& e : a)
	{
		s.insert(e);
	}
	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	for (auto& e : s)
	{
		cout << e << " ";
	}

看一下运行结果
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
我们再来看一下一个的返回值
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
这个地方就有很大的意义了。
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
count的意义也就发挥出来了。

四.map

map就是对应我们二叉树中的KV模型

1.map文档介绍

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
看一下模板参数
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
包括四个值:
🌟Key:键值对中的key值
🌟T:键值对中的value值
🌟Compare:比较器类型,一般是按照小于比较。如果是自定义类型,需要自己传递这个比较方式,达到要求。
🌟Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的
空间配置器

set文档介绍

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

看一下要点:
🌟🌟map中存储的是一个键值对,键值对中第一个元素,也就是key,根据key值进行排序,确定唯一元素。
第二个值value,与key的内容关联。
🌟🌟元素不可以修改key的值,但是可以修改value的值。
🌟🌟支持下标访问,把key放在[ ]中,可以找到与之对应的value元素。

2.map成员函数

这其中与很多和set的成员函数相同,在这里我就不再重复阐述了。
接下来主要讲述一些不同点,以及重点内容。
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

1.构造

🌟🌟1.有名构造
    pair<string, string>p = { “pear”, “梨” };
    m.insert( p);
🌟🌟2.匿名构造
   m.insert(pair<string, string>(“apple”, “苹果”));
🌟🌟3.make_pair
    m.insert(make_pair(“banana”, “香蕉”));
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
c++98新增的,本质就是一个函数模板

🌟🌟4.c++11多参数隐式类型转换
    m.insert({“strawberrier” ,“草莓”});

2.insert插入

我们看一下官方文档
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
我们主要看一下第一条:

插入的是一个pair类型,返回值也是一个pair类型

我们来看一下有关返回值的介绍
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

如果插入到元素存在,返回值中的iterator就指向这个存在的位置的迭代器,bool值为false
如果插入元素不存在,返回值中的iterator就指向这个新插入的位置的迭代器,bool值为true
这里的元素插入是看key的值,与value无关。

3.count

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
count返回key为x的键值在map中的个数,注意map中key是唯一的,因此该函数的返回值要么为0,要么为1,因此也可以用该函数来检测一个key是否在map中。

4.迭代器

我们注意一下map有两个值,我们再遍历的时候,不能只遍历一个,要把两个分开。


	for (auto& kv : m)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;

first代表pair第一个值,second代表pair第二个值。

5.【】和at

map中支持【】访问元素。

如果我们想要统计水果出现的次数
第一步:先看这个水果在不在!!
第二步:如果不在,就把这一个键值对插入进去。如果在,就让vaule这个值加加。
最后遍历一边元素,就完成了

我们再map中不用折磨麻烦,我们看一下这个巧妙的代码。

// 统计水果出现的次数
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
map<string, int> m;
for (auto& e : arr)
{
	m[e]++;
}

m[e]++;就完成了操作。

我们来看一下怎末实现的??
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
【】的返回值是value类型,参数是一个key类型。

在文档中还有这样一段话,我们来剖析一下。
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

这个【】需要调用insert,insert上面我们已经介绍过了,拆分来看一下
🌟insert(make_pair(k,mapped_type()))这个是insert的原型,插入一个键值对,key值必须传入,如果value不传入,采用缺省值。
这个k存在,就返回这个k这个值的迭代器,不存在,就返回新插入这个k的迭代器。
🌟this->insert(make_pair(k,mapped_type()))调用这个返回值pair
🌟(this->insert(make_pair(k,mapped_type()))).first调用这个返回值的pair的第一个元素iterator,迭代器本身就是指针。
🌟(*((this->insert(make_pair(k,mapped_type()))).first)).second
这个迭代器指向的第二个元素,就是value.

通过这种方式我们就拿到了value的值
如果不存在,插入成功,返回新插入元素的迭代器
如果已存在,插入失败,返回该key所在位置的迭代器
operator[]函数最后将insert返回值键值对中的value返回

在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用
不同的是:当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常。

我们看一下这段代码的结果是什么??

	map<string, string> dict;
	dict.insert(make_pair("sort", "排序"));
	dict.insert(make_pair("string", "字符串"));
	dict.insert(make_pair("sort", "xxx"));

C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

只与key的值有关,与value无关。
key相同,value不同,不会插入也不会更新

这个【】就有很多功能了,也可以插入,也可以查找,也可以修改
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

五.multimap

map和multimap没有太大区别
C++set和map详细介绍,C嘎嘎,c++,容器,STL,map,set,multimap,multiset

  1. Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key,value>,其中多个键值对之间的key是可以重复的。
  2. 在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合key和value的键值对:
    typedef pair<const Key, T> value_type;
  3. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的。
  4. multimap通过key访问单个元素的速度通常unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列。
  5. multimap在底层用二叉搜索树(红黑树)来实现

multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的。
multimap中没有重载operator[]操作

总结

以上就是今天要讲的内容,本文仅仅详细介绍了C++map和set的相关内容。希望对大家的学习有所帮助,仅供参考 如有错误请大佬指点我会尽快去改正 欢迎大家来评论~~ 😘 😘 😘文章来源地址https://www.toymoban.com/news/detail-845876.html

到了这里,关于C++set和map详细介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】map、set、multimap、multiset的介绍和使用

    我讨厌世俗,也耐得住孤独。 1. 之前所学的vector,list,deque等容器都是序列式容器,因为他们的底层数据结构都是线性的,并且数据结构中存储的都是元素数据本身,也就是单一的变量。 而下面所学的set、map、multimap、multiset等容器都是关联式容器,他们内部存储的不再是单

    2023年04月15日
    浏览(31)
  • map、multimap、set、multiset讲解

    2023年07月10日
    浏览(34)
  • 详解map、set、multimap、multiset的使用

    ✍ 作者 : 阿润菜菜 📖 专栏 : C++ map、set、multimap、multiset是C++ STL中的四种关联容器,它们内部都使用了红黑树这种高效的平衡检索二叉树来存储数据 。它们的区别和用法如下: map是一种 键值对 容器,它可以根据键来快速查找、插入和删除值,它的键是唯一的,不能重复

    2024年02月03日
    浏览(22)
  • 【C++】map/multimap/set/multiset的经典oj例题 [ 盘点&全面解析 ] (28)

    前言 大家好吖,欢迎来到 YY 滴C++系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《初学者易

    2024年02月04日
    浏览(34)
  • STL --- 二、容器 (4)set 和multiset

    目录 1、std::set 和 std::multiset 特点 2、std::set 和 std::multiset 常用的api 3、std::set 和 std::multiset 的示例 4、std::map和set区别 1、std::set 和 std::multiset 特点 (1)std::set 中每个元素的键值都唯一,而 std::multiset 中可以有多个相同的键值。 (2)std::set 中的元素按照键值大小顺序是按照元

    2024年02月06日
    浏览(30)
  • C++STL——map/multimap容器详解

    纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 在STL中有些容器的元素是一种叫pair的数据结构。 对组(pair)是类模板,对组(pair)将一对值组合成一个值,一般用于表示key/value数据,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公

    2024年02月14日
    浏览(32)
  • Google 开源库Guava详解(集合工具类)—Maps、Multisets、Multimaps

    Maps有许多很酷的实用程序,值得单独解释。 Maps.uniqueIndex(Iterable,Function)解决了一个常见的情况,即有一堆对象,每个对象都有一些唯一的属性,并希望能够根据该属性查找这些对象。 假设我们有一堆字符串,我们知道它们有唯一的长度,我们希望能够查找具有特定长度

    2024年02月03日
    浏览(30)
  • C++高级编程——STL:list容器、set容器和map容器

    本专栏记录C++学习过程包括C++基础以及数据结构和算法,其中第一部分计划时间一个月,主要跟着黑马视频教程,学习路线如下, 不定时更新,欢迎关注 。 当前章节处于: ---------第1阶段-C++基础入门 ---------第2阶段实战-通讯录管理系统, ---------第3阶段-C++核心编程, -----

    2024年01月25日
    浏览(37)
  • 19 标准模板库STL之set和multiset

    基础知识         1、set是一个自动有序且不含重复元素的容器,内部使用红黑树的平衡二叉索引树的数据结构来实现。向set中插入新元素时,会自动调节二叉树的排列,将元素放到合适的位置。multiset与set不同的地方在于,set内相同数值的元素只能出现一次,multiset内相同

    2023年04月22日
    浏览(38)
  • 【C++入门到精通】C++入门 —— set & multiset (STL)

    前面我们讲了C语言的基础知识,也了解了一些初阶数据结构,并且讲了有关C++的命名空间的一些知识点以及关于C++的缺省参数、函数重载,引用 和 内联函数也认识了什么是类和对象以及怎么去new一个 ‘对象’ ,也了解了C++中的模版,以及学习了几个STL的结构也相信大家都

    2024年02月08日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包