C++进阶篇章:set与map(pair , multiset , multimap)

news2024/10/6 1:38:41

目录

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

2.pair(键值对)

3.set

构造函数

find函数

count函数:

insert函数

4.multiset

5.map

insert函数

operator[]


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

C++中关联式容器与序列式容器是两种不同的容器

   1.关联式容器

关联式容器:

  1. 关联式容器主要包括 std::set, std::map, std::multiset, std::multimap 等。
  2. 这些容器是基于键值对(<key, value>结构)的概念,通过键==(key)来唯一标识元素==。
  3. 关联式容器内部使用二叉搜索树(通常是红黑树)或类似的数据结构,以保持元素的有序性。
  4. 插入、删除、查找等操作的平均时间复杂度是 O(log n)。

序列式容器:

  1. 序列式容器包括 std::vector, std::list, std::deque, std::array 等。
  2. 这些容器是基于线性结构的,元素在容器中的位置是由插入的顺序决定的。
  3. 插入、删除、查找等操作的平均时间复杂度因容器类型而异,但在最差情况下,可能达到 O(n)。

2.pair(键值对)

C++中有一种数据结构,他能将两种不同的数据类型给强制的绑定,形成相连关系

定义:pair包含在<utility> 的头文件中 ,其中pair中有两个成员变量 , 一个是first , 另一个就是second 

STL库中pair的定义(没有具体实现swap,make_pair等函数)

template <class T1, class T2>
struct pair
{
	
	T1 first;
	T2 second;

	pair(T1 a = T1() , T2 b = T2() ) //构造函数
	: first(a), second(b)
	{}

	pair(const T1& a, const T2& b) //拷贝构造
	: first(a), second(b)
	{}
};

pair的构造函数

1.构造函数

具体代码实现请看上面

实例:

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<queue>
#include<utility>
using namespace std;
int main()
{
    pair<int, int> t(1, 1);
    pair<int, int> k;
    cout << t.first << " " << t.second << endl;
    cout << k.first << " " << k.second << endl;
    return 0;
}

2.拷贝构造函数

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<queue>
#include<utility>
using namespace std;
int main()
{
    pair<int, int> t(1, 1);// 构造函数
    pair<int, int> k = t;// 拷贝构造函数
    pair<int, int> s(t);// 拷贝构造函数
    cout << t.first << " " << t.second << endl;
    cout << k.first << " " << k.second << endl;
    cout << s.first << " " << s.second << endl;
    return 0;
}

3.make_pair函数(函数模版)

传入key , value 生成 pair , 并返回pair

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<queue>
#include<utility>
using namespace std;
int main()
{
    pair<string, string> t = { "abc" , "def" };
    t = make_pair<string,string>("afad", "fasd");
    cout << t.first << " " << t.second << endl;
    return 0;
}

3.set

  1. set是按照某一次序存储元素的
  2. set是key值模型,但也存在value(并且value = key ),set中key(value)值不能修改
  3. 底层使用红黑树实现的

构造函数

1.迭代器区间构造

2.拷贝构造

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{
    vector<string> ret = { "a" , "b" , "c" };
    set<string>  ans(ret.begin(), ret.end());
    set<string> k = ans;
    for (auto& e : ans)
        cout << e << endl;

    return 0;
}

find函数

给定一个key,如果set中存在,返回该节点的迭代器,不存在,返回set.end()

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{
    vector<string> ret = { "a" , "b" , "c" };
    set<string>  ans(ret.begin(), ret.end());
    auto it = ans.find("a");
    if (it != ans.end())
        cout << *it << endl;
    else
        cout << "不存在" << endl;
    return 0;
}

count函数:

给定一个key值 ,如果set中存在,返回1 , 不存在,返回0(与find函数相似)

int main()
{
    vector<string> ret = { "a" , "b" , "c" };
    set<string>  ans(ret.begin(), ret.end());
    int i = ans.count("a");
    if (i)cout << i << endl;
    else cout << i << endl;
    return 0;
}

insert函数


声明:pair<iterator, bool> insert(const value_type& val);

插入元素到 set 中。


如果插入成功,返回一个迭代器指向插入的位置和 true。


如果元素已经存在,返回一个迭代器指向已存在的元素和 false。


返回一个 pair 对象,包含插入的迭代器和插入是否成功的标志。

int main()
{
    vector<string> ret = { "a" , "b" , "c" };
    set<string>  ans(ret.begin(), ret.end());
    ans.insert({ "d" });
    return 0;
}

  1. 删除一个迭代器所指向的节点
  2. 删除某一特定的值
  3. 删除某一迭代区间(左闭右开)
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{
    set<string> ret = { {"ab"} , {"cd"} , {"ef"} };
    ret.erase("ab");// 删除某一特定的值
    for (auto& e : ret)
        cout << e << endl;
    cout << endl;
    ret.insert({ "ab" });
    ret.erase(ret.begin());// 删除某一迭代器
    for (auto& e : ret)
        cout << e << endl;
    cout << endl;
    ret.insert({ "ab" });
    ret.insert({ "tt" });
    auto it = ret.find("tt");
    ret.erase(ret.begin(), it);
    for (auto& e : ret)
        cout << e << endl;
    return 0;
}

4.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底层结构为二叉搜索树(红黑树)

注意:

  1. multiset中再底层中存储的是<value, value>的键值对
  2. mtltiset的插入接口中只需要插入即可
  3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的
  4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
  5. multiset中的元素不能修改
  6. 在multiset中找某个元素,时间复杂度为O ( l o g 2 N ) 
  7. multiset的作用:可以对元素进行排序

multiset 是 C++ 标准库中的关联式容器之一,属于有序容器。与 set 不同的是,multiset 允许键值重复,即可以包含相同键值的多个元素。

允许重复键值: multiset 允许容器中存在相同的键值,因此可以包含多个相同键值的元素。

有序性: 与 set 类似,multiset 也维护元素的有序性,根据键值进行排序。

当需要允许键值重复,并且希望保持元素有序时,可以选择使用 multiset。

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{
    vector<int> k = { 2,1,5,6,7,3,1,1,1,90 };
    multiset<int> ret(k.begin(), k.end());
    for (auto& e : ret)cout << e << " ";
    cout << endl;
    return 0;
}

5.map

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

5.1map 模板参数说明

  1. key: 键值对中key的类型
  2. T: 键值对中value的类型
  3. Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
  4. Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

构造函数

1.迭代器区间构造

2.拷贝构造

insert函数

void test()
{
    map<int,int> ret;
    ret.insert({1,1});
    ret.insert(make_pair(1,1));
    auto tmp = make_pair(1,1);
    ret.insert(tmp);
}

operator[]

返回的是关于value的引用

1.读取元素:当使用 [] 运算符时

  • 如果指定的键存在于 map 中,则返回与该键关联的值
  • 如果不存在,则会插入一个新的键值对,键为指定的键,值为默认构造的对应值类型的默认值,并返回该默认值的引用

2.插入元素:当使用 [] 运算符向 map 中插入元素时

  • 如果指定的键不存在,则会创建一个新的键值对,键为指定的键,值为指定的值,并返回该值的引用
  • 如果键已经存在,则直接返回对应的值的引用。
#include<iostream>
#include<map>
using namespace std;
int main()
{
    map<int, int> ret;
    vector<int> ans = { 1, 2, 3, 4, 5,6 ,6,7, };
    for (auto& e : ans)
    {
        ret[e]++;// 插入pair
    }
    for (auto& e : ret)
    {
        cout << e.first << " " << e.second << endl;
    }
    ret[1] = 10; // 修改pair
    return 0;
}

erase

第一种:删除 key 为某一个值的pair

#include<iostream>
#include<map>
using namespace std;
int main()
{
    map<int, int> ret;
    vector<int> ans = { 1, 2, 3, 4, 5,6 ,6,7, };
    for (auto& e : ans)
    {
        ret[e]++;
    }
    for (auto& e : ret)
    {
        cout << e.first << " " << e.second << endl;
    }
    ret.erase(1);
    cout << endl;
    for (auto& e : ret)
    {
        cout << e.first << " " << e.second << endl;
    }
    return 0;
}

第二种:删除某一迭代区间(左闭右开)


#include<iostream>
#include<map>
using namespace std;
int main()
{
    map<int, int> ret;
    vector<int> ans = { 1, 2, 3, 4, 5,6 ,6,7, };
    for (auto& e : ans)
    {
        ret[e]++;
    }
    for (auto& e : ret)
    {
        cout << e.first << " " << e.second << endl;
    }
    auto p1 = ret.find(3);
    auto p2 = ret.find(6);
    cout << endl;
    ret.erase(p1, p2);
    for (auto& e : ret)
    {
        cout << e.first << " " << e.second << endl;
    }
    return 0;
}

6.multimap

multimap的基本性质

  • multimap容器是和map容器相似的关联式容器,所谓“相似”,是指multimap容器具有和map容器相同的特性,即multimap容器也存储pair<const K, T>类型的键值对(其中K表示键的类型,T表示值的类型),其中各个键值对的键的值不能被修改;并且,该容器也会自行根据键的大小对所存储的所有键值对做排序操作。
  • multimap容器和map容器的区别在于,multimap容器中可以同时存储多个键相同的键值对。
  • multimap容器提供的成员方法,map容器都有提供,并且它们的用法是相同的。详细的用法请参照map的用法及实例详解。本文只是给出了所有在multimap中的成员函数及其实现功能,具体的实例及代码请参照map容器。
  • 实现multimap容器的类模板也定义在<map>头文件,并位于std命名空间中,故使用multimap容器前,应该引入头文件:#include<map>

构造函数

创建空的multimap

multimap<int,int> ret;

创建multimap并初始化(注意用{})

multimap<int, int> ret{ { 1,1 }, { 2,3 }, { 5,6 } };

拷贝构造

multimap<int,int> ans(ret);

迭代区间构造


#include<iostream>
#include<map>
#include<climits>
using namespace std;
int main()
{

    multimap<int, int> ret{ { 1,1 }, { 2,3 }, { 5,6 } };
    multimap<int, int> ans(++ret.begin(),ret.end());
    for (auto& e : ans)cout << e.first << " " << e.second << endl;
 
    return 0;
}

常见成员函数和使用方法:

注意multimap并没有重载operator[]

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python Cookbook】S01E01 将长度为N的序列分解为N个单独的变量

目录 问题解决方案讨论 问题 将一个包含 N N N 个元素的元组或者序列&#xff0c;现在想将其分解为 N N N 个单独的变量。 解决方案 任何序列都可以通过简单的赋值操作分解为单独的变量&#xff1a; p (4, 5) x, y p print("x", x) print("y", y)唯…

合约之间调用-如何实现函数静态调用?

合约之间的函数调用 EOA&#xff0c;external owned account&#xff0c;外部账号&#xff0c;例如metamask调用最终总是由EOA发起的合约之间的调用使得一次完整的调用成为一个调用链条 合约间调用过程 调用者须持有被调用合约的地址得到被调用合约的信息将地址重载为被调用合…

ChatGPT的工作原理,这篇文章说清楚了!

作者&#xff1a;史蒂芬沃尔弗拉姆&#xff08;Stephen Wolfram&#xff09;英、美籍 计算机科学家&#xff0c; 物理学家。他是 Mathematica 的首席设计师&#xff0c;《一种新科学》一书的作者。 ChatGPT 能够自动生成一些读起来表面上甚至像人写的文字的东西&#xff0c;这…

c#点击listview控件获取内容

构造函数添加&#xff1a; 点击事件&#xff1a; &#xff08;listview控件确保有内容&#xff0c;比如已查询到数据添加到了listview&#xff09; if (listView_data_base.Items.Count > 0){listView_data_base.FullRowSelect true;listView_data_base.Items[listView_da…

Django 解决 CSRF 问题

在 Django 出现 CSRF 问题 要解决这个问题&#xff0c;就得在 html 里这么修改 <!DOCTYPE html> <html><head></head><body><form action"/login/" method"post">{% csrf_token %}</form></body> </…

Vue3项目练习详细步骤(第三部分:文章分类页面模块)

文章分类列表 主体结构 接口文档 文章分类列表查询接口数据绑定 Pinia状态管理库 axios请求拦截器 Pinia持久化插件-persist 未登录统一处理 添加文章分类 主体结构 接口文档 绑定请求数据 编辑文章分类 弹框结构 数据回显 接口文档 绑定请求数据 删除分类 …

CPU占用率很高,相应很慢排查思路

获取线程状态 通过top -c命令可以动态显示进程及其占用资源的排行榜 可以看到&#xff0c;CPU占用率100%的PID是80972&#xff0c;定位到该进程之后&#xff0c;我们再从线程的dump日志中去定位. 使用top -H -p 80972命令查找到该进程中消耗CPU最多的线程&#xff0c;从下面的…

海外社媒账号如何运营安全稳定?

由于设备与网络原因&#xff0c;通常一个海外社媒账号尤其是多账号的稳定性都有一定限制&#xff0c;错误的操作或者网络都可能使得账号被封&#xff0c;前功尽弃。本文将为大家讲解如何通过IP代理来维持账号稳定与安全&#xff0c;助力海外社媒矩阵的搭建。 一、社媒账号关联…

金蝶云星空数据库迁移后,显示 error: 40 - 无法打开到 SQL Server 的连接的解决方法

原因&#xff1a;数据库迁移/或者更新IP后&#xff0c;与之前添加的数据库地址不一致导致无法连接数据库&#xff1b; 解决方法&#xff1a;修改IP为目前数据库的IP&#xff1b; 文件路径&#xff1a;在ManageSite\APP_Data\Common.config中&#xff0c;修改DbServerInstance…

数据源不同?奥威BI软件是这么做的

面对数据源不同的情况&#xff0c;BI&#xff08;商业智能&#xff09;软件如奥威BI软件通常通过一系列技术和方法来实现数据的整理。以下以奥威BI软件为例&#xff0c;详细解释其如何整理不同数据源的数据&#xff1a; 数据收集&#xff1a; 爬虫技术&#xff1a;奥威BI软件…

【车载开发系列】Autosar DEM中重要配置项说明

【车载开发系列】Autosar DEM中重要配置项目 【车载开发系列】Autosar DEM中重要配置项目说明 【车载开发系列】Autosar DEM中重要配置项目1&#xff09;DemDtcStatusAvailabilityMask2&#xff09;DemTypeOfDTCSupported3&#xff09;DemFreezeFrameCapture4&#xff09;DemIm…

3D模型三角面转四角面操作指南---模大狮模型网

在3D建模的过程中&#xff0c;三角面(Triangles)和四角面(Quads)是两种常见的多边形类型。虽然三角面在渲染速度和计算效率上有其优势&#xff0c;但四角面在模型编辑和纹理映射上通常更为方便。因此&#xff0c;将三角面转换为四角面是建模过程中常见的需求。 一、选择合适的建…

【YOLOv5/v7改进系列】引入AKConv——即插即用的卷积块

一、导言 介绍了一种名为AKConv&#xff08;Alterable Kernel Convolution&#xff09;的新型卷积操作&#xff0c;旨在解决标准卷积操作存在的两个根本性问题。首先&#xff0c;标准卷积操作受限于局部窗口&#xff0c;无法捕获来自其他位置的信息&#xff0c;且其采样形状固…

URL在线编码解码

URL在线编码解码 打开网站 在线工具网-梦幻加菲猫 选择“URL编码解码” 输入需要编码/解码的内容&#xff0c;点击“编码”/“解码”按钮 编码&#xff1a; 解码&#xff1a; 复制已经编码/解码后的内容。

Mac安装tomcat

代码 brew install tomcat 运行结果如下&#xff1a; 如果要启动输入&#xff1a; brew services start tomcat

php 安装 swoole扩展

一 在swoole官网查询适配版本Swoole 文档 2. php环境为7.3下载 4.8 ​ wget https://pecl.php.net/get/swoole-4.6.6.tgztar -zxvf swoole-4.6.6.tgzcd swoole-4.6.6/usr/local/php7/bin/phpize​ ./configure --enable-openssl --enable-sockets --enable-mysqlnd --enabl…

【车载开发系列】Vector工具链的安装

【车载开发系列】Vector工具链的安装 【车载开发系列】Vector工具链的安装 【车载开发系列】Vector工具链的安装一. VectorDriver二. DaVinci_Developer三. DaVinci Configurator 一. VectorDriver Vector Driver Setup是Vector产品链中重要的驱动软件,所有的硬件设备进行连接…

springboot课程题库管理系统-计算机毕业设计源码30812

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于课程题库管理系统 当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了课程题库管理系统 &#xff0c;它彻底改变了…

基于深度学习的中文情感分析系统python flask

基于python的毕业设计 基于深度学习的中文情感分析系统(flask)(源码说明文档演示) 毕业设计课程设计期末大作业、课程设计、高分必看&#xff0c;下载下来&#xff0c;简单部署&#xff0c;就可以使用。 包含&#xff1a;项目源码、数据库脚本、软件工具等&#xff0c;该项目…

R语言入门 | 使用 dplyr 进行数据转换

3.1简介 3.1.1准备工作 3.1.2 dplyr 基础 • 按值筛选观测&#xff08; filter() &#xff09;。 • 对行进行重新排序&#xff08; arrange() &#xff09;。 • 按名称选取变量&#xff08; select() &#xff09;。 • 使用现有变量的函数创建新变量&#xff08; …