C++_map与set

目录

一、set

1、set的用法

2、multiset

二、map

1、map的用法 

2、map的operator[]

3、multimap

结语


前言:

        C++中的map和set容器属于关联式容器,与序列式容器不同的地方在于(序列式容器即vector、list,其底层是由线性数据结构实现的容器),关联式容器存储的是键值对,键值对是一个结构体,他只有两个成员变量:key,value,并且key和value是一一对应的,key表示键值,而value就是key对应的数据。

        关联式容器的底层由两种结构实现:树型结构(红黑树)、哈希结构。树型结构实现的容器有:map、multimap、set、multiset,哈希结构实现的容器有:unordered_map和unordered_set,本文着重介绍树型结构实现的容器。正是因为关联式容器在底层的结构上采用比序列式容器更为复杂的结构,所以关联式容器在查找数据时效率较序列式容器更高。

一、set

template < class T,                        class Compare = less<T>,        class Alloc = allocator<T>      > class set;

1、set的用法

        set只有唯一标识数据,即:value,但是这个value属于键值,也就是前面讲到的key,简单来说就是set在底层也是以键值对存放的,只不过键值对中不是<key,value>,而是<value,value>。并且通过value的值来确定其存放的顺序。

        set作为STL的容器之一,自然是可以实现数据的存储,只不过一般容器可以实现增删查改的功能,而set只能实现增删查的功能,原因就在于set的底层是红黑树(搜索二叉树),存放在set中的数据实际上存储在红黑树的节点中,红黑树的节点都是按照严格的规则进行摆放的,若修改一个数则会导致大消耗的调整,因此set不允许修改数据。但也正是红黑树,所以在迭代数据时,可以按照大小来打印数据(中序遍历树结构)。

        set的测试代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include<set>
#include<iostream>
using namespace std;int main()
{set<int> s1;//插入大量重复数据s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(1);s1.insert(2);s1.insert(1);s1.insert(3);set<int>::iterator it1 = s1.begin();while (it1 != s1.end())//迭代器遍历{cout << *it1 << " ";++it1;}cout << endl;s1.erase(3);//删除3// 打印删除后数据for (auto e : s1){cout << e << " ";}cout << endl;return 0;
}

        运行结果:

        从结果可以看到,set还具备去重的功能,并且打印出来的数据是具有顺序的,这些set的自带功能在特殊的场景下用起来是非常方便的。

        但是有一个问题,对象s1的类型是int,虽然底层存放的是键值对<value,value>,但是到了用户使用的应用层做了优化,只需要显示传递一个value类型即可,否则set的模板参数显示传递就要写<int,int>了,过于麻烦。

2、multiset

        multiset与set的区别在于:multiset允许存储重复的值。并且删除的值如果是重复的,那么该值都会被删除。

        multiset测试代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include<set>
#include<iostream>
using namespace std;int main()
{multiset<int> s1;//插入大量重复数据s1.insert(3);s1.insert(1);s1.insert(4);s1.insert(1);s1.insert(2);s1.insert(1);s1.insert(3);set<int>::iterator it1 = s1.begin();while (it1 != s1.end())//迭代器遍历{cout << *it1 << " ";++it1;}cout << endl;s1.erase(3);//删除3// 打印删除后数据for (auto e : s1){cout << e << " ";}cout << endl;return 0;
}

        运行结果:

二、map

template < class Key,                                     class T,                                       class Compare = less<Key>,                     class Alloc = allocator<pair<const Key,T> >    > class map;

1、map的用法 

        map与set的区别在于,map的键值对是<key,value>,通常用pair结构体来表示这个键值对。以key的值来确定每个pair类型元素的顺序序列并且key所在的元素必须唯一(即去重),value的值是与key相关联的数据。

        pair结构体的结构如下:

template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())//默认构造
{}
pair(const T1& a, const T2& b): first(a), second(b)//带参数的构造函数
{}
};

        map测试代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
#include<map>
using namespace std;int main()
{map<string, string> dict;dict.insert(pair<string, string>("sort", "排序"));//检查去重dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("count", "计数"));auto dit = dict.begin();while (dit != dict.end()){//先对迭代器dit解引用拿到pair结构体,然后在解引用拿到pair中的成员first和secondcout << (*dit).first << ":" << (*dit).second << endl;++dit;}cout << endl;return 0;
}

        运行结果:

        从结果可以看到,map的插入函数需要手动构建一个pair作为该函数的实参,而这里用到的make_pair是一个函数模板,该函数会返回一个pair对象,这样就能够达到inset函数的要求了。

        具体示意图如下:

2、map的operator[]

        map的operator[]运算符重载用法很经典,我们对[]的认识是,他可以查看数组中某一位置的值,并且可以修改这个元素,而map的operator[]在以上功能的前提下还具备插入功能,只不过对map的[]修改是更改value的内容,而不更改key的内容,同理通过[]对map的查看是查看元素中value的值。


        以下map的operator[]的实现示意图可以更好的解释其功能:

         ret是一个对象,他用来接收Insert的返回值,他跟Insert的make_pair返回的临时对象是两个对象,ret对象中里面有一个迭代器,该迭代器指向通过Insert函数插入到map中pair元素。operator[]的返回值实际上就是通过ret找到插入元素的第二个成员变量value,并且返回他的引用,所以[]可以更改map中元素的value数据。

        测试operator[]的代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
#include<map>
using namespace std;int main()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("count", "计数"));dict["ZH"];	// 成功插入,但是value值没有显示给,因此value调用string的默认构造--即nullptrdict["OBJ"] = "后缀"; // 插入+修改,插入的元素key为OBJ,value从nullptr修改成"后缀"dict["sort"] = "(排序)"; // 修改,将key:sort从原来的排序修改为“排序”cout << dict["sort"] << endl; // 查找,打印sort的valuecout << endl;auto dit = dict.begin();while (dit != dict.end()){//cout << (*dit).first << ":" << (*dit).second << endl;cout << dit->first << ":" << dit->second << endl;++dit;}cout << endl;return 0;
}

        运行结果:

        注意:所以map插入和修改都是可以直接用【】,但是【】的查找功能用起来会有弊端,如果要查找的元素不在map里面就会自动插入一个该元素,失去了单纯查找的本意。 

3、multimap

        multimap与map的区别在于:前者允许key值冗余,即不会对数据起到去重的作用。

        multimap测试代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>
#include<map>
using namespace std;int main()
{multimap<string, string> dict;dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("count", "计数"));dict.insert(make_pair("count", "计数"));auto dit = dict.begin();while (dit != dict.end()){//cout << (*dit).first << ":" << (*dit).second << endl;cout << dit->first << ":" << dit->second << endl;++dit;}cout << endl;return 0;
}

        运行结果:

结语

        以上就是关于map和set以及multimap、multiset的讲解,实际中map和set还是用的最多,他们的区别无非在于set只有一个value作为key键值而map中即有key键值也有与其对应的value键值,也正是因为set没有value键值,所以set没有实现‘[]'的运算符重载,而map实现了‘[]'的运算符重载。

        最后希望本文可以给你带来更多的收获,如果本文对你起到了帮助,希望可以动动小指头帮忙点赞👍+关注😎+收藏👌!如果有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/503598.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国际光伏展

国际光伏展即国际光伏产业展览会&#xff0c;是全球范围内最具规模和影响力的光伏产业展览会之一。光伏展是一个专门展示和推广光伏技术和产品的平台&#xff0c;汇聚了全球各类光伏企业、研究机构和专家学者&#xff0c;是光伏行业交流、合作和发展的重要场所。 国际光伏展通常…

java中开源json处理库介绍

在Java生态系统中&#xff0c;有几个常用的开源库用于处理JSON数据。这些库各有特点&#xff0c;适用于不同的场景。下面我将介绍几个流行的Java JSON处理库&#xff0c;包括它们的基本情况、主要特点和核心API。 Jackson 基本情况 Jackson是一个流行的Java库&…

Tomcat服务部署、优化

一 Tomcat的基本介绍 Tomcat概念 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试 JSP 程序的首选。 当在一台机器上配置好Apache 服务器…

uniApp 调整小程序 单个/全部界面横屏展示效果

我们打开uni项目 小程序端运行 默认是竖着的一个效果 我们打开项目的 pages.json 给需要横屏的界面 的 style 属性 加上 "mp-weixin": {"pageOrientation": "landscape" }界面就横屏了 如果是要所有界面都横屏的话 就直接在pages.json 的 gl…

FlinkSQL ChangeLog

01 Changelog相关优化规则 0101 运行upsert-kafka作业 登录sql-client&#xff0c;创建一个upsert-kafka的sql作业&#xff08;注意&#xff0c;这里发送给kafka的消息必须带key&#xff0c;普通只有value的消息无法解析&#xff0c;这里的key即是主键的值&#xff09; CREA…

python3.x的在线与离线安装纯净版

由于计划搭建一套使用python自动分析日志的流程&#xff0c;发现我们的测试环境CentOS 7仍然没有安装python3&#xff0c;无法使用这些新的库。Python 3在设计上着重提升了语言的一致性和易用性&#xff0c;它引入了许多关键改进&#xff0c;此外&#xff0c;Python 3环境拥有丰…

机器学习 | 模型性能评估

目录 一. 回归模型的性能评估1. 平均平方误差(MSE)2. 平均绝对误差(MAE)3. R 2 R^{2} R2 值3.1 R 2 R^{2} R2优点 二. 分类模型的性能评估1. 准确率&#xff08;Accuracy&#xff09;2. 召回率&#xff08;Recall&#xff09;3. 精确率&#xff08;Precision&#xff09;4. …

sqlserver unique约束示例

UNIQUE 和 PRIMARY KEY 约束均为列或列集合提供了唯一性的保证。 PRIMARY KEY 拥有自动定义的 UNIQUE 约束。 与主键约束类似&#xff0c;唯一约束也强制唯一性&#xff0c;但唯一约束用于非主键的一列或者多列的组合&#xff0c;且一个表可以定义多个唯一约束。 有如下表&…

Linux运维-Web服务器的配置与管理(Apache+tomcat)(没成功,最后有失败经验)

Web服务器的配置与管理(Apachetomcat) 项目场景 公司业务经过长期发展&#xff0c;有了很大突破&#xff0c;已经实现盈利&#xff0c;现公司要求加强技术架构应用功能和安全性以及开始向企业应用、移动APP等领域延伸&#xff0c;此时原来开发web服务的php语言已经不适应新的…

02-prometheus监控-服务器节点监控node-exporter

一、概述 prometheus&#xff0c;本身是一个【数据收集】和【数据处理】的工具&#xff0c;如果效果要监控一台服务器物理机&#xff0c;有两种方式&#xff0c;一种是在物理机上部署“node-export”来收集数据上报给prometheus&#xff0c;另一种是“自定义监控”&#xff1b;…

PowerDesigner中怎么给ER图中字段设置默认值

双击table&#xff0c;进入数据库表详情页 详情页点击【Columns】 双击你要设置默认值得栏目&#xff0c;例如我得删除标记 点击【Standard Checks】&#xff0c;在【Defalut】中录入你想要得默认值&#xff0c;点击【应用即可】

Window10安装ruby

最好的方法&#xff0c;使用rubyinstaller&#xff0c;即在Downloads。 这是官方推荐的安装方式 通常来说我们会下载64位的 下载完后执行下载的exe即可。在最后一步会提示让安装gem&#xff0c;选则安装即可。 然后就可以在控制台进行测试了。