C++ map set

一.关联式容器

在初期学过的vector、list、deque、forward_list(C++11)等,底层都为线性序列的序列式容器。

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

二.键值对

键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该单词,在词典中就可以找到与其对应的中文含义。

在SGI-STL中关于键值对的定义:

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)
	{}
};

三.set

set介绍

1.set是按照一定次序存储元素的容器。

2.在set中,元素的value也表示它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能再容器中修改(元素总是const),但是可以从容器中插入或删除它们。

3.在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。

4.set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。

5.set在底层是用二叉搜索树(红黑树)实现的。

6.set中插入元素时,只需要插入value即可,不需要构造键值对。

7.set中的元素不可以重复(因此可以使用set去重)。

8.set中的元素默认按照小于来比较。

9.set中查找某个元素,时间复杂度为O(logn)。

10.set中的元素不允许修改。

12.与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对,因此在set容器中插入元素时,只需要插入value即可,不需要构造键值对。

set定义

    set<int> s1;//1.空的set容器

    set<int> s2(s1);//2.用已有的s1拷贝构造s2

    string str("bear");
    set<char> s3(str.begin(), str.end());//3.用迭代器区间构造

set使用

插入删除操作

insert(x)当容器中没有等价元素的时候,将元素 x 插入到 set 中
erase(x)删除值为 x 的 所有 元素,返回删除元素的个数
erase(pos)删除迭代器为 pos 的元素,要求迭代器必须合法
erase(first,last)删除迭代器在 [first,last) 范围内的所有元素
clear清空容器
swap交换两个容器的数据

 查找操作

count(x)返回 set 内键为 x 的元素数量
find(x)在 set 内存在键为 x 的元素时会返回该元素的迭代器,否则返回 end()
lower_bound(x)返回指向首个不小于给定键的元素的迭代器。如果不存在这样的元素,返回 end()
upper_bound(x)返回指向首个大于给定键的元素的迭代器。如果不存在这样的元素,返回 end()
empty()返回容器是否为空
size()返回容器内元素个数

 迭代器

begin()/cbegin()返回指向首元素的迭代器,其中 *begin = front
end()/cend()返回指向数组尾端占位符的迭代器,注意是没有元素的
rbegin()/crbegin()返回指向逆向数组的首元素的逆向迭代器,可以理解为正向容器的末元素
rend()/crend()返回指向逆向数组末元素后一位置的迭代器,对应容器首的前一个位置,没有元素

 以上列出的迭代器中,含有字符 c 的为只读迭代器,你不能通过只读迭代器去修改 set 中的元素的值。如果一个 set 本身就是只读的,那么它的一般迭代器和只读迭代器完全等价。只读迭代器自 C++11 开始支持。

 下列对常用的函数进行模拟:

#include<iostream>
#include<set>
using namespace std;

int main()
{
    set<int> s1;
    //insert函数
    s1.insert(1);
    s1.insert(2);
    s1.insert(3);
    s1.insert(4);
    s1.insert(5);
    s1.insert(6);
    //遍历一,范围for
    for (auto i : s1)
    {
        cout << i << " ";
    }
    cout << endl;//1 2 3 4 5 6

    //指定元素个数
    cout << s1.count(1) << endl;//1个

    //容器大小
    cout << s1.size() << endl;//6
    
    //erase函数1
    s1.erase(6);//删除元素6

    //erase函数2
    set<int>::iterator pos = s1.find(5);
    if (pos != s1.end())
    {
        s1.erase(pos);
    }

    //遍历二(正向迭代器)
    set<int>::iterator it = s1.begin();
    while (it != s1.end())
    {
        cout << *it << " ";
        it++;
    }
    cout << endl;//1 2 3 4

    //clear函数
    s1.clear();

    //容器判空
    cout << s1.empty() << endl;//1

    //遍历方式三(反向迭代器)
    set<int>::reverse_iterator rit = s1.rbegin();
    while (rit != s1.rend())
    {
        cout << *rit << " ";
        rit++;
    }
    cout << endl;//   为空
}

multiset

multiset与set的底层与函数基本相同,不同的是multiset可以允许键值冗余,也就是说multiset容器中的元素是可以重复的

四.map

map介绍

1.map是关联式容器,它按照特定的次序(按照key来比较)存储由key和值value组合而成的元素。

2.在map中,键值key通常用于排序和唯一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map内部,key与value通过成员类型valur_type绑定在一起,为其取别名称为pair: (typedef pair <const key,T> value_type);

3.在内部,map中的元素总是按照键值key进行比较排序的。

4.map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,就可以找到与key对应的value)。

5.map支持下标访问,即在[]中放入key,就可以找到与key对应的value。

6.map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

map定义

    map<int, int> m1;//构造一个key和value都为int的空容器

    map<int, int> m2(m1);//拷贝m1构造一个key和value都为int的空容器

    map<int, int> m3(m2.begin(), m2.end());//用迭代器构造一个key和value都为int的空容器

map使用

map插入

在map中插入,需要同时插入key和value

再来看看map插入函数的原型

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

insert函数的参数显示为value_type类型,实际上value_type就是pair类型的别名

typedef pair<const Key, T> value_type;

所以,我们向map容器插入元素时,需要用key和value构造一个pair对象,然后再将pair对象作为参数传入insert函数。

调用make_pair函数模板插入

库中会提供make_pair模板:

template <class T1, class T2>
pair<T1, T2> make_pair(T1 x, T2 y)
{
	return (pair<T1, T2>(x, y));
}

我们只需要向make_pair函数传入key和value,该函数模板会根据传入参数类型进行自动隐式推导,最终构造并返回一个对应的pair对象。

#include<iostream>
#include<map>
using namespace std;

int main()
{
    //map插入
    map<int, string> m1;
    m1.insert(make_pair(1, "one"));
    m1.insert(make_pair(2, "two"));
    m1.insert(make_pair(3, "three"));
    for (auto i : m1)
    {
        cout << "<" << i.first << "," << i.second << ">";
        cout << endl;
    }
    cout << endl;//<1,one> <2,two> <3,three>
    return 0;
}

在前面我们可以看到,insert函数是有返回值的,该返回值也是一个pair对象,该pair对象第一个成员的类型是map的迭代器类型,第二个成员的类型是一个bool类型,下面介绍具体含义:

1.若带插入元素的键值key在map当中不存在,则insert函数插入成功,并返回插入后元素的迭代器和true。

2.若待插入元素的键值key在map当中已经存在,则insert函数插入失败,并返回map当中键值为key的元素迭代器和false。

map查找

map查找函数的原型为:

iterator find(const key_type& k);

该函数含义为,根据所给的key值在map中进行查找,假如找到了,那么返回对应元素的迭代器;如果没找到,那么返回最后一个元素下一个位置的正向迭代器。

#include<iostream>
#include<map>
using namespace std;

int main()
{
    map<int, string> m1;
    m1.insert(make_pair(1, "one"));
    m1.insert(make_pair(2, "two"));
    m1.insert(make_pair(3, "three"));

    //map查找
    map<int, string>::iterator pos = m1.find(3);
    if (pos != m1.end())
    {
        cout << pos->second << endl;//three
    }
    return 0;
}

map删除

先来看看map删除函数的原型:

size_type erase(const key_type& k);

void erase(ietrator posision);

根据函数原型可以看到,可以根据key删除指定元素,也可以根据迭代器删除指定元素。要是根据key删除,那么返回删除元素的个数。

#include<iostream>
#include<map>
using namespace std;

int main()
{
    map<int, string> m1;
    m1.insert(make_pair(1, "one"));
    m1.insert(make_pair(2, "two"));
    m1.insert(make_pair(3, "three"));


    //map删除
    cout << m1.erase(3);//1
    map<int, string>::iterator pos = m1.find(1);
    if (pos != m1.end())
    {
        m1.erase(pos);
    }
    return 0;
}

map的[]运算符重载

map的[]运算符重载函数原型为:

mapped_type& operator[] (const key_type& k);

可以看到,[]运算符重载函数的参数是一个key值,而这个函数的返回值如下:

(*((this->insert(make_pair(k, mapped_type()))).first)).second

 我们将它进行拆解分析:

1.调用insert函数插入键值对。

2.拿出从insert函数获取到的迭代器。

3.返回该迭代器位置元素的值value。

下面来看看拆解代码:

mapped_type& operator[] (const key_type& k)
{
	//1、调用insert函数插入键值对
	pair<iterator, bool> ret = insert(make_pair(k, mapped_type()));

	//2、拿出从insert函数获取到的迭代器
	iterator it = ret.first;

	//3、返回该迭代器位置元素的值value
	return it->second;
}

再来看看具体使用场景:

#include <iostream>
#include <string>
#include <map>
using namespace std;

int main()
{
	map<int, string> m1;
	m1.insert(make_pair(1, "one"));
	m1.insert(make_pair(2, "two"));
	m1.insert(make_pair(3, "three"));
	m[2] = "bear"; //修改key值为2的元素的value为bear
	m[4] = "four"; //插入键值对<4, "four">
	for (auto e : m)
	{
		cout << "<" << e.first << "," << e.second << ">" << " ";
	}
	cout << endl; //<1,one> <2,bear> <3,three> <4,four>
	return 0;
}

总结:

1.如果k不在map中,那么先插入键值对<k,V()>,然后返回该键值对中对V对象的引用。

2.如果k在map中,则返回键值为k的元素对应V对象的引用。

map迭代器

begin获取容器中第一个元素的正向迭代器
end获取容器中最后一个元素下一个位置的正向迭代器
rbegin获取容器中最后一个元素的反向迭代器
rend获取容器中第一个元素前一个位置的反向迭代器

使用方法和set的相同。

map的其它成员函数

size获取容器中元素的个数
empty判断容器是否为空
clear清空容器
swap交换两个容器中的数据
count获取容器中指定key值的元素个数

multimap

multimap与map和multiset与set的关系几乎相同,multimap也允许键值冗余

在find函数中:

map对象的find功能为:返回值为键值为key的元素的迭代器。

multimap对象的find功能为:返回底层搜索树中序的第一个键值为key的元素的迭代器。

在count函数中:

map对象的count功能为:键值为key的元素存在则返回1,不存在则返回0(find成员函数可代替)

multimap对象的count功能为:返回键值为key的元素个数(find成员函数不可代替)。

另外,由于multimap容器允许键值冗余,调用[ ]运算符重载函数时,应该返回键值为key的哪一个元素的value的引用存在歧义,因此在multimap容器当中没有实现[ ]运算符重载函数。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小程序支付的款项流转与到账时间

商家做小程序&#xff0c;最关心的是客户通过小程序下单支付的钱&#xff0c;是怎么样的流转状态以及最终到哪里。因此&#xff0c;本文将详细解析款项最终流向何处以及多久能够到账。 一、小程序支付的款项流向 当用户在小程序内完成支付后&#xff0c;款项并不会直接到达商…

CSRF漏洞简介

csrf简介 CSRF 全称为跨站请求伪造&#xff08; Cross-site request forgery &#xff09;&#xff0c;是一种网络攻击方式&#xff0c;在 CSRF 的攻击场景中攻击者会伪造一个请求&#xff08;这个请求一般是一个链接&#xff09;&#xff0c;然后欺骗目标用户进行点击&#xf…

C51版本Keil + STC-ISP 实现第一盏灯,从创建到实现

创建项目 1. 新建项目 Project -> New uVision Project 2.1 新建文件夹 2.2 输入文件名称, 并保存 3.1 选择当前位STC芯片的开发板&#xff0c;选择STC MCU Database 搜素具体芯片型号&#xff0c;进行配置&#xff1a; 3.2 选择通过搜索框搜索到stc相关芯片信息 如果st…

linux数据备份与恢复

目录 前言 1、数据备份和恢复中的两个关键性指标 2、linux系统的定时任务 1&#xff09;本地定时任务crontab 在实验测试过程中&#xff0c;遇到多次crontab任务不执行问题 &#xff0c;总结下来主要有几个方面原因&#xff1a; 2)分布式定时任务系统Jenkins 3、备份存储…

机房——蓝桥杯十三届2022国赛大学B组真题

问题分析 这题用深搜广搜都能做&#xff0c;不过我更倾向于用广搜&#xff0c;因为广搜能更容易找到目标点。那么是采用结构体存储边还是采用二维数组存储临接矩阵呢&#xff1f;我们注意到n的取值范围为1e5,用二维数组哪怕是bool类型就需要至少1e10Byte的连续空间,这个空间太大…

为软件教学文档增加实践能力

为了更方便软件教学&#xff0c;我们在凌鲨(OpenLinkSaas)上增加了公共资源引用的功能。 目前可以被引用的公共资源: 微应用常用软件公共知识库Docker模板 引用公共资源 引用微应用 目前微应用包含了主流数据库&#xff0c;终端等工具&#xff0c;可以方便的进行各种相关实…

【25届秋招备战C++】23种设计模式

【25届秋招备战C】23种设计模式 一、简介程序员的两种思维8大设计原则 二、具体23种设计模式2.1 创建型模式2.2 结构性模式2.3 行为型模式 三、常考模式的实现四、参考 一、简介 从面向对象谈起&#xff0c; 程序员的两种思维 底层思维:向下 封装&#xff1a;隐藏内部实现 多…

ASP.NET小型证券术语解释及翻译系统的设计与开发

摘 要 在系统设计上&#xff0c;综合各种翻译类型网站优缺点&#xff0c;设计出具有任何使用者都可添加术语信息的且只有管理员能够实现术语修改及删除等独特方式的术语查看管理系统。此方式能够使术语量快速增大&#xff0c;并且便于使用者及管理员操作&#xff0c;满足相互…

软件设计师-应用技术-面向对象程序设计题5

考题形式&#xff1a; 代码填空&#xff0c;5 - 6空&#xff0c;每空3分。 基础知识及技巧&#xff1a; 1. 类的定义&#xff1a; 2. 接口的定义&#xff1a; 给实现类具体代码&#xff0c;填写接口中方法。 3. 类、抽象类、继承类、抽象方法的定义&#xff1a; 抽象类&…

【管理咨询宝藏95】SRM采购平台建设内部培训方案

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏95】SRM采购平台建设内部培训方案 【格式】PDF版本 【关键词】SRM采购、制造型企业转型、数字化转型 【核心观点】 - 重点是建设一个适应战略采…

20240508请问GTX2080TI的300和300A核心的差异?

20240508请问GTX2080TI的300和300A核心的差异&#xff1f; 在拼多多/淘宝上&#xff0c;GTX2080TI的300A核心的会比300核心的贵100&#xffe5;左右。 但是怎么区分呢&#xff1f; 300a核心和300请问怎么区分呢&#xff1f;[嘻嘻] devicr ID diviceid 1e07是300a 1e04是300 Gp…

2024041702-计算机操作系统 - 死锁

计算机操作系统 - 死锁 计算机操作系统 - 死锁 必要条件处理方法鸵鸟策略死锁检测与死锁恢复 1. 每种类型一个资源的死锁检测2. 每种类型多个资源的死锁检测3. 死锁恢复 死锁预防 1. 破坏互斥条件2. 破坏占有和等待条件3. 破坏不可抢占条件4. 破坏环路等待 死锁避免 1. 安全状态…

使用 Parallels Desktop 在 Mac 上畅玩 PC 游戏

我们不再需要接受 “Mac 不是为游戏而打造” 这一事实&#xff1b;Parallels Desktop 通过将电脑变成高性能的游戏设备&#xff0c;从而改变了一切。 Parallels Desktop 充分利用 Mac 硬件的强大功能&#xff0c;让您无缝畅玩 Windows 专享游戏。 性能得到提升&#xff0c;可玩…

基于 llama2 的提示词工程案例2

优化大型语言模型&#xff08;LLMs&#xff09; 优化大型语言模型&#xff08;LLMs&#xff09;中的提示词&#xff08;prompts&#xff09;是提高模型性能和输出相关性的重要手段。以下是一些优化提示词的方向&#xff1a; 明确性&#xff1a;确保提示词清晰明确&#xff0c;…

数据湖与数据网格:引领组织数据策略的未来

十多年来&#xff0c;组织已经采用数据湖来克服数据仓库的技术限制&#xff0c;并发展成为更加以数据为中心的实体。虽然许多组织已经使用数据湖来探索新的数据用例并改进其数据驱动的方法&#xff0c;但其他组织发现所承诺的好处很难实现。因此&#xff0c;许多数据湖计划的有…

SOLIDWORKS Electrical电气元件智能开孔

实际的电气元器件安装中&#xff0c;一些元器件需要穿过孔洞安装&#xff0c;例如按钮、指示灯会在配电柜的控制面板上&#xff0c;需要穿过控制面板安装。这部分内容放在软件建模、装配时&#xff0c;往往比较复杂因为考虑孔的大小符合元器件规格、孔跟随元器件移动、同一元器…

CR80清洁卡的重要性

在我们日常生活中&#xff0c;身份证、银行卡、信用卡等塑料卡片已经成为了不可或缺的一部分。这些卡片通常符合CR80标准&#xff0c;这意味着它们的尺寸和厚度符合国际标准&#xff0c;为了保证这些卡片的读取和使用效果&#xff0c;清洁维护显得尤为重要。 什么是CR80卡&…

Linux学习之禁用防火墙

查看防火墙状态 systemctl status firewalld.service 第一行前面的圆圈是有颜色的就是开启状态 黑色的就是关闭状态 关闭防火墙 systemctl stop firewalld.service 输入密码认证 再次查看防火墙状态 systemctl status firewalld.service 第一行前面的圆圈变成黑色说明关闭…

杰理-701-单线灯-ws2812-驱动

杰理-701-单线灯-ws2812-驱动 LED_gradual_open(); //调用后 呼吸灯 set_led_colour&#xff08;R,G,B&#xff09;&#xff1b;//具体颜色 spi_dma_set_addr_for_isr //spi 配置dma 后灯才亮 #define LED_H 0x7c #define LED_L 0x40 发送高位和地位的字节&#xff0c;具体…

UP互助 帮助UP起号做视频 支持B站和抖音

【软件名字】&#xff1a;UP互助 【软件版本】&#xff1a;1.0 【软件大小】&#xff1a;17.5MB 【软件平台】&#xff1a;安卓 【测试机型】&#xff1a;小米9 1.随便登个邮箱&#xff0c;添加自己平台的频道&#xff0c;然后就可以帮助别人&#xff0c;添加频道后在添加…
最新文章