前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++/STL】map和set介绍

【C++/STL】map和set介绍

作者头像
秦jh
发布2024-07-23 08:01:21
690
发布2024-07-23 08:01:21
举报
文章被收录于专栏:c语言,c++

前言

💬 hello! 各位铁子们大家好哇。 今日更新了map和set的相关内容 🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

关联式容器

vector、list、deque等这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。

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

树形结构的关联式容器

STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset

set

set的介绍
  • 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。 set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  • set在底层是用二叉搜索树(红黑树)实现的。

注意:

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对,set中只放 value,但在底层实际存放的是由构成的键值对。
  2. set中插入元素时,只需要插入value即可,不需要构造键值对。
  3. set中的元素不可以重复(因此可以使用set进行去重)。
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列
构造

简单使用:

set的使用很简单,主要功能是key模型的搜索,次要功能是排序+去重。

set还支持迭代器区间构造和花括号构造。

删除

erase参数可以是值,也可以是迭代器。如果传值,如果有该值就删除,没有就没变化。erase还可以迭代器区间删除。

查找删除
lower_bound

上方是迭代器区间删除的例子。lower_bound就是大于等于,upper_bound就是大于,即左闭右开的区间。

multiset

multiset和set的区别就是允许冗余,不去重。

有多个相同的数时,multiset的find会找中序遍历的第一个 。

map

map的介绍

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

value_type就是pair<const Key, T>。

插入

map插入时,类型得是pair。

插入的方式有很多,make_pair相当于函数模板,它会自动识别类型。最后一行是initializer_list的隐式类型转换构造。

遍历

不能直接对迭代器解引用,因为里面有两个值。所以这里的用法跟前面list的模拟很像。

注意上面传引用比较好,这样就不会因为进行深拷贝,而导致效率低下。


operator[]

上面的写法太过麻烦,可以使用[]。 如下图:

operator[]的使用相当于下面函数的作用:

自行翻译一下就变成下面的代码:

里面使用了insert,下面是insert的返回值:

解释一下版本(1)的返回值: 当插入pair后,返回值也是pair。该pair的first指向新插入的节点的迭代器或者已存在节点的迭代器,second为bool值,插入成功返回true,失败返回false。 即:key存在,插入失败,返回pair<存在的key所在节点的迭代器,false> key不存在,插入成功,返回pair<新插入的key所在节点的迭代器,true>

了解了operator[]的底层实现,就有了其他用法:

operator[]的本质:给[]一个Key,如果存在,就返回Key对应val的引用。如果不存在,就插入Key,然后val给的是缺省值(string缺省值就是"") 。

count

count在map中一般用来判断是否存在,在multimap中可以用来数个数。

multimap

当我们想按数量排序时,因为有相同数量的水果,就需要用multimap。multimap没有重载[],所以只能使用insert。multimap不能重载[],因为已经允许冗余了,如果key有多个,就不知道返回哪个key对应的val。

注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的。

测试代码

代码语言:javascript
复制
#include<iostream>
#include<set>
#include<map>
#include<vector>

using namespace std;

void test_set1()
{
	//主要功能:key模型搜索
	//次要功能:排序+去重
	set<int> s1;
	s1.insert(1);
	s1.insert(11);
	s1.insert(3);
	s1.insert(1);
	s1.insert(4);
	s1.insert(2);
	set<int>::iterator it = s1.begin();
	while (it != s1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	vector<int> v = { 3,2,8,1,10,2 };
	set<int> s2(v.begin(), v.end());
	for (auto e : s2)
	{
		cout << e << " ";
	}
	cout << endl;

	set<int>s3 = { 3,2,8,1,10,2 };
	for (auto e : s3)
	{
		cout << e << " ";
	}
	cout << endl;
	s3.erase(8);
	s3.erase(18);
	for (auto e : s3)
	{
		cout << e << " ";
	}
	cout << endl;

	auto pos = s3.find(10);
	if (pos != s3.end())
	{
		cout << *pos << endl;
		s3.erase(pos);
	}
	else
	{
		cout << "找不到" << endl;
	}
	for (auto e : s3)
	{
		cout << e << " ";
	}
	cout << endl;

}

void test_set2()
{
	set<int> myset;
	for (int i = 1; i < 10; i++) 
		myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90

	for (auto e : myset)
	{
		cout << e << " ";
	}
	cout << endl;
	//[30,70)
	auto itlow = myset.lower_bound(30);         //   >=   
	auto itup = myset.upper_bound(60);          //   >              

	myset.erase(itlow, itup);           // 10 20 70 80 90

	for (auto e : myset)
	{
		cout << e << " ";
	}
	cout << endl;
}

void test_set3()
{
	//主要功能:key模型搜索
	//次要功能:排序 不去重
	multiset<int> s1;
	s1.insert(1);
	s1.insert(2);
	s1.insert(11);
	s1.insert(3);
	s1.insert(1);
	s1.insert(4);
	s1.insert(2);
	multiset<int>::iterator it = s1.begin();
	while (it != s1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	auto pos = s1.find(2);
	while (pos != s1.end()&&*pos==2)
	{
		cout << *pos << " ";
		++pos;
	}
}

void test_map1()
{
	map<string, string> dict;
	pair<string, string> kv1("sort", "排序");
	dict.insert(kv1);
	dict.insert(pair<string, string>("left", "左边"));
	dict.insert(make_pair("right", "右边"));

	// 隐式类型转换
	//单参数和多参数都支持隐式类型转换
	//如果是多参数,用花括号括起来即可
	pair<string, string> kv2 = { "string","字符串" };
	dict.insert({ "string","字符串" });

	map<string, string> dict2 = { {"left", "左边"},{"right", "右边"} };

	map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{
		//cout << *it << " ";  //错误
		cout << (*it).first << ":" << (*it).second << endl;
		cout << it->first << ":" << it->second << endl;
		cout << it.operator->()->first << ":" << it.operator->()->second << endl;

		++it; 
	}
	cout << endl;

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

void test_map2()
{
	string arr[] = { "苹果","西瓜","苹果","西瓜","苹果","苹果","西瓜","苹果","香蕉",
	"苹果","香蕉","苹果","草莓","苹果","草莓" };
	map<string, int> countMap;
	for (auto& e : arr)
	{
		countMap[e]++; 
		/*auto it = countMap.find(e);
		if (it != countMap.end())
		{
			it->second++;
		}
		else
		{
			countMap.insert({ e,1 });
		}*/
	}
	for (auto& kv : countMap)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;
	 
	multimap<int, string> sortMap;
	for (auto& kv : countMap)
	{
		//sortMap[kv.second] = kv.first;
		sortMap.insert({ kv.second,kv.first });
	}
	cout << endl;

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

void test_map3()
{
	map<string, string> dict;
	dict.insert({ "string","字符串" });

	//插入(一般不这么用)
	dict["right"];

	//插入+修改
	dict["left"] = "左边";
	
	//"查找"
	cout << dict["string"] << endl;

	//修改
	dict["right"] = "右边";

	string str;
	cin >> str;
	if (dict.count(str))
	{
		cout << "在" << endl;
	}
	else
	{
		cout << "不在" << endl;
	}
}

int main()
{
	test_map3();
	return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 关联式容器
  • 树形结构的关联式容器
    • set
      • set的介绍
      • 构造
      • 删除
      • 查找删除
      • lower_bound
    • multiset
    • map
      • map的介绍
        • 插入
          • 遍历
            • operator[]
              • count
              • multimap
              • 测试代码
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档