当前位置: 首页 > article >正文

【C++打怪之路Lv16】-- map set

🌈 个人主页:白子寰
🔥 分类专栏:重生之我在学Linux,C++打怪之路,python从入门到精通,数据结构,C语言,C语言题集👈 希望得到您的订阅和支持~
💡 坚持创作博文(平均质量分82+),分享更多关于深度学习、C/C++,python领域的优质内容!(希望得到您的关注~)

序列式容器和关联式容器

序列容器如string、vector等存储线性数据,元素按存储顺序访问

关联容器如map、set基于红黑树实现,提供基于关键字的存储和访问

其中set存储唯一关键字(对应key模型),map存储键值对(对应key/value模型)



set系列的使用

set和multiset参考文档

<set> - C++ Reference


set类的介绍

set声明采用类型T,需支持小于比较或自定义比较函数

底层使用红黑树存储,内存由空间配置器管理,可选自定义。

通常无需指定后两个模板参数

set操作效率为O(log n),迭代器按中序遍历提供有序访问。


set的使用

insert && 范围for && 迭代器


find查找区别 && count


lower_bound && upper_bound 


multiset 


multiset和set的差异

在C++中,set和multiset都是关联容器,用于存储已排序的数据集合。

它们的主要区别在于它们对键值(或元素)的重复性的处理方式

  • set

set容器中不允许有重复的元素。每个元素都是唯一的。
当尝试插入一个已经在set中存在的元素时,插入操作将失败,并且容器保持不变。
set通常实现为一个红黑树,这意味着在set中查找、插入和删除操作的时间复杂度通常是O(log n)

  • multiset

multiset容器允许存储重复的元素。
在multiset中可以插入相同的元素多次,每个元素都会被独立存储。
与set一样,multiset也是基于红黑树实现的,因此它也提供了对元素的排序,并且查找、插入和删除操作的时间复杂度通常是O(log n)

  • 查找操作

在set中,由于元素唯一,find操作会返回指向找到元素的迭代器,或者如果没有找到则返回end()迭代器。
在multiset中,find操作同样可以用来查找元素,但由于可能有多个相同的元素,它只保证返回一个匹配元素的迭代

  • 删除操作

在set中,erase操作会删除指定的元素(如果存在),并且由于元素唯一,只会删除一个匹配的元素。
在multiset中,erase操作可以删除所有匹配的元素,或者只删除一个特定的实例


选择使用set还是multiset取决于你的具体需求:

如果你需要确保元素的唯一性,应该使用set

如果你需要存储多个相同的元素并保持它们的排序,则应该使用multiset



map系列的使用

map和multiset参考文档

<map> - C++ Reference


map类的介绍

C++中的map类是一种关联容器,它存储键值对,其中键是唯一的,而值则可以是重复的。map类属于STL(标准模板库)的一部分,它按照键的升序自动排序。

以下是map类的一些基本特性和用法:

特性

  1. 键的唯一性:在map中,每个键都是唯一的,不能有重复的键。
  2. 自动排序map根据键的值自动排序,默认是升序。
  3. 键值对存储map存储键值对,可以通过键快速访问对应的值。
  4. 红黑树实现map通常是基于红黑树实现的,这意味着插入和查找操作的时间复杂度为O(log n)

map的使用

map的四种插入方式、迭代器的使用及范围for

void Test1()
{
	map<string, string> dict;
	
	// 一、
	pair<string, string> kv1 = {"left", "左边"};
	dict.insert(kv1);

	// 二、
	dict.insert(pair<string, string>("right", "右边"));

	// 三、
	dict.insert(make_pair<string, string>("up", "上边"));

	// 四、
	dict.insert({ "down","下边" });

	// 五、
	map<string, string> dict1 = { {"left", "左边"},{"right", "右边"},{"up", "上边"},{"down","下边"} };

	// 迭代器
	map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{
		cout << (*it).first << ":" << (*it).second << endl;
		++it;
	}

	cout << endl;

	// 范围for①
	for (auto& e : dict1)
	{
		cout << e.first << ":" << e.second << endl;
	}

	cout << endl;

	// 范围for②
	for (auto& [x, y] : dict1)
	{
		cout << x << ":" << y << endl;
	}
}


map简单字典的实现

int main()
{
	map<string, string> dict = { { "left","左边" }, { "right","右边" }, { "up","上边" }, { "down","下边" } };
	string str;
	while (cin >> str)
	{
		auto ret = dict.find(str);
		if (ret != dict.end())
		{
			cout << "-->" << ret->second << endl;
		}
		else
		{
			cout << "查无此单词" << endl;
		}
	}
	return 0;
}

 CTRL + Z 退出


使用map对于水果(牛奶)的计数 

int main()
{
	string arr[] = { "苹果","香蕉","牛奶","苹果","香蕉","苹果","牛奶" };
	map<string, int> CountFruit;
	for (auto& str : arr)
	{
		auto ret = CountFruit.find(str);
		if (ret == CountFruit.end())
		{
			CountFruit.insert({ str,1 });
		}
		else
		{
			ret->second++;
		}
	}

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

	return 0;
}


multimap和map的差异

multimap和map在C++中都是关联容器,用于存储键值对,但它们之间有几个关键差异:

  • 唯一性

map:在map中,每个键必须是唯一的。如果你尝试插入一个具有相同键的元素,它将替换掉具有相同键的现有元素。
multimap:与map不同,multimap允许键重复。因此,你可以有多个具有相同键的元素。

  • 实现方式

map:通常是基于红黑树实现的,这使得元素按照键的升序排列,并保证查找、插入和删除操作的时间复杂度为O(log n)。
multimap:同样基于红黑树实现,但由于允许多个相同键的存在,其行为略有不同。

  • 操作

插入:

对于map,插入操作会检查键是否已存在,如果存在则替换旧值。

对于multimap,插入操作不会检查键的唯一性,因此可以插入多个相同键的元素
查找:

在map中,你可以使用find()函数查找特定的键,并且最多只能找到一个匹配项。

在multimap中,find()函数将返回第一个匹配的键值对,但你可能需要使用equal_range()函数来找到所有具有相同键的元素。
删除:

在map中,使用erase()函数可以删除具有特定键的单个元素。

在multimap中,erase()函数可以删除具有特定键的所有元素,或者你可以指定一个迭代器来删除单个元素。

  • 总结

选择map还是multimap取决于你的具体需求。

如果你需要每个键对应唯一的值,那么应该使用map

如果你需要存储具有相同键的多个值,那么应该使用multimap



**********************************************************分割线*****************************************************************************
完结!!!
感谢浏览和阅读。

等等等等一下,分享最近喜欢的一句话:

“万年太久,只争朝夕”。

我是白子寰,如果你喜欢我的作品,不妨你留个点赞+关注让我知道你曾来过。
你的点赞和关注是我持续写作的动力!!! 
好了划走吧。


http://www.kler.cn/a/414552.html

相关文章:

  • scrapy豆瓣爬虫增强-批量随机请求头
  • Mybatis-基础操作
  • C#面向对象,封装、继承、多态、委托与事件实例
  • Windows修复SSL/TLS协议信息泄露漏洞(CVE-2016-2183) --亲测
  • mac下Gpt Chrome升级成GptBrowser书签和保存的密码恢复
  • 实时数据开发 | 一文理解Flink窗口机制
  • 【新人系列】Python 入门(十三):函数进阶
  • 【jvm】什么是动态编译
  • 【金猿案例展】京东物流UData——物流行业数据分析智能体解决方案
  • Perplexica - AI 驱动的搜索引擎
  • 亚马逊反爬二之限流
  • FreeRTOS之链表源码分析
  • Android Studio 使用插件Database Navigation 连接 sqlite数据库
  • PHP学习_1
  • 【通俗理解】Transformer中位置编码与词嵌入的分离
  • GAMES101:现代计算机图形学入门-笔记-09
  • yolov5的pt模型转化为rk3588的rknn,并在rk3588上调用api进行前向推理
  • 鸿蒙启航日志:探索华为科技之旅的第一天
  • 【Bug】el-date-picker组件时间差
  • 23种设计模式-装饰器(Decorator)设计模式
  • Python websocket
  • BC-Linux8.6上面手动安装Postgresql17(Docker版)
  • 永久免费的PDF万能水印删除工具
  • AD软件如何快速切换三维视图,由2D切换至3D,以及如何恢复
  • Lumoz TGE在即,NFT助力提前解锁esMOZ
  • TDengine(涛数)据库安装保姆级教程