map和set的使用(基于STL库)

news2024/11/24 20:35:26

前言

        map和set是STL模板库中重要的关联式容器,与序列式容器不同的是,关联式容器里面存储的是<key,value>结构的键值对,在数据检索时比序列式容器效率更高。让我们一起来看看吧!

目录

1.set

        1.1键值对

        1.2set的介绍

        1.3set的使用 

        1.3.1set的模版参数列表

        1.3.2set的构造函数

        1.3.3set的迭代器

        1.3.4与容量相关的

        1.3.5set的增删查

2.map 

        2.1map的介绍

        2.2map的使用 

        2.2.1 map的模版参数说明

        2.2.2map的构造

        2.2.3map的迭代器

        2.2.4增删查

        2.2.5容量相关

        2.2.6例子

3.multiset

4.multimap


1.set

        和其他容器一样set可以进行增删查,但是不能改变它的值,因为它的底层是用平衡搜索树来实现的额,如果将节点的值改变,就会破坏平衡搜索树的性质,因此改变它是非法的。 

        1.1键值对

        键值对是用来表示一一对应关系的一种结构,该结构中包含两个变量成员,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)
    {}
};

        1.2set的介绍

        set的介绍 

        关于set使注意事项:

        1.与map/multimap不同,map/multimap中储存的是真正的键值对<key,value>,set中只放value,但是底层实际上是由<value,value>构成的键值对。

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

        3.set中的元素不可重复。

        4.使用set迭代器遍历set中的元素实际上平衡树的中序遍历。

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

        6.set查找某个元素,时间复杂度为:logN。

        7.set的元素不允许修改

        8.set底层是由红黑色来实现的

        1.3set的使用 

        1.3.1set的模版参数列表

        

        1.T中存放存放元素的类型,底层实际上存储的<value,value>键值对。

        2. Compare:set中的默认元素按照小于来比较的

        3.Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

        1.3.2set的构造函数

        

函数声明表
函数声明功能介绍
set (const Compare& comp = Compare(), const Allocator&
= Allocator() );
构造空的set
set (InputIterator first, InputIterator last, const
Compare& comp = Compare(), const Allocator& =
Allocator() );
用[first,last]区间的元素构造set
set ( const set<Key,Compare,Allocator>& x);set的拷贝构造

        1.3.3set的迭代器

        与其他容器一样set也可以使用迭代器遍历,并且set只能使用迭代器遍历。         

        

迭代器函数声明表
函数声明功能
iterator begin()返回set起始位置的元素的迭代器
iterator end()返回set最后一个位置后面的迭代器
const_iterator cbegin()
const
返回set起始位置的const迭代器
const_iterator cend() const返回set最后一个位置后面的const迭代器
reverse_iterator rbegin()返回set起始位置的反向迭代器,即end
reverse_iterator rend()返回set最后一个元素下一个位置的迭代器,即rbegin
const_reverse_iterator
crbegin() const
返回set起始位置的反向const迭代器,即cend
const_reverse_iterator
crend() const
 返回set最后一个元素下一个位置的反向const      迭代器,即crbegin

        1.3.4与容量相关的

函数声明表
函数声明功能介绍
bool empty ( ) const检测set是否为空,返回值是bool值,为空返回true
size_type size() const返回set中有效元素的个数

        1.3.5set的增删查

函数声明表
函数声明功能介绍
void erase ( iterator position )删除迭代器position位置的元素
size_type erase ( const
key_type& x )
删除值为x的元素
void erase ( iterator first,
iterator last )

删除set中[first,last)区间的元素

void swap (
set<Key,Compare,Allocator>&
st );
交换set中的元素
void clear ( )将set清空
iterator find ( const
key_type& x ) const
返回值为x的迭代器
size_type count ( const
key_type& x ) const
返回值为x的元素个数

2.map 

        2.1map的介绍

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

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

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

        4.map通过键值访问单个元素的速度通常比unordered_map慢,但是map允许根据顺序对元素直接迭代(即对map中的元素进行迭代可以得到一个有序序列)。

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

        6.map通过被实现为红黑色。

        2.2map的使用 

        2.2.1 map的模版参数说明

template < class Key,                                     // map::key_type           class T,                                       // map::mapped_type           
class Compare = less<Key>,                     // map::key_compare           
class Alloc = allocator<pair<const Key,T> >    // map::allocator_type           
> class map;

 key:对应键值对中的key类型。

T:键值对中的value类型

Compare:比较器类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)不需要传递参数,如果无法比较时(自定义类型),需要用户自己显示传递比较规则(一般情况下按照函数指针或者仿函数来传递)

Allloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器。

        2.2.2map的构造

函数声明功能介绍
map构造一个空的map

        2.2.3map的迭代器

迭代器函数声明表
函数声明功能介绍
begin()和end()begin:首元素的位置,end:最后一个元素下一个元素的位置
cbegin()和cend()与begin和end的意义相同,但是cbegin和cend所指的元素不能修改
rbegin()和rend()

反向迭代器,rbegin在end位置,rend在begin位置,其++和--都是与begin和end操作相反的移动。

crbegin()和crend()

与rbegin和rend位置相同,操作相同,但是crbegin和crend所指向的不能修改

        2.2.4增删查

函数声明功能介绍
pair<iterator,bool> insert (
const value_type& x )
在map中插入一个键值对x,注意x是一个键值对,返回值也是一个键值对,iterator代表新插入元素的位置,bool代表释放插入成功
void erase ( iterator position )删除迭代器position位置的元素
size_type erase ( const
key_type& x )
删除键值为x的元素
void erase ( iterator first,
iterator last )
删除[first,last)区间中的元素
void swap (
map<Key,T,Compare,Allocator>&
mp )
交换两个map中的元素
void clear ( )将map中的元素清空
iterator find ( const key_type& x
)
在map中查找key值为x的元素,找到返回该元素的位置的迭代器,否则返回end
const_iterator find ( const
key_type& x ) const
在map中查找key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend

        2.2.5容量相关

函数声明功能简介
bool empty ( ) const检测map中是否为空,如果为空返回true
size_type size() const返回map中的有效元素的个数
mapped_type& operator[] (const
key_type& k)
返回key对应的value

         如果使用operator[]时没有找到key值,即当key不存在时,operator[]用默认的value与key构造键值对然后插入,返回默认的value,at()函数抛出异常。

        2.2.6例子

#include<iostream>
#include<map>
#include<set>
#include<string>
using namespace std;
void map1()
{
	//使用map来统计水果出现的次数
	string s[] = { "西瓜", "西瓜", "菠萝", "西瓜", "苹果", "苹果", "西瓜",
		"西瓜", "菠萝", "菠萝", "哈密瓜","甜枣","甜枣","荔枝" };
	map<string, int> mp;
	for (auto& e : s)
	{
		map<string, int>::iterator it = mp.find(e);
		if (it != mp.end())
		{
			it->second++;//存在的水果次数就加加
		}
		else
		{
			mp.insert(make_pair(e,1));//不存在就插入
		}
	}
	for (auto& e : mp)
		cout << e.first << " " << e.second << endl;
}

void map2()
{
	map<string, string> m;
	//向map中插入元素
	//将键值对<"apple","苹果">插入map中,用pair来构造键值对
	m.insert(pair<string, string>("apple", "苹果"));
	//将键值对<"orange","橙子">插入到map中,用make_pair来构造键值对
	m.insert(make_pair("orange", "橙子"));
	//用operator[]向map中插入元素
	m["pear"] = "梨子";
	//key不存在时抛异常
	//
	cout << m.size();
	//遍历map
	for (auto& e : m)
		cout << e.first << ": " << e.second << endl;
	//map中的键值对key一定是唯一的
	//如果key存在将插入失败
	auto e = m.insert(make_pair("apple", "苹果"));
	if (e.second)
	{
		cout << "<apple,苹果>不在map中, 已经插入" << endl;

	}
	else
	{
		cout << "键值为peach的元素已经存在:" << endl;

	}
	auto e1 = m.erase("apple");//删除键值对为“Apple”的元素
	if (e1)
	{
		cout << "删除apple成功!" << endl;
	}
	else
	{
		cout << "删除apple失败!" << endl;
	}
}
void maps()
{
	string s[] = { "西瓜", "西瓜", "菠萝", "西瓜", "苹果", "苹果", "西瓜",
		"西瓜", "菠萝", "菠萝", "哈密瓜","甜枣","甜枣","荔枝" };
	map<string, int> m;
	for (auto& e : s)
		m[e]++;//通过调用map的operator[]来统计水果出现的次数
	for (auto& e : m)
		cout << e.first << ":" << e.second << endl;
}

        可以通过map中的operator[]来对水果出现的次数进行统计,这和其他容器的opreator[]不同,它是怎么做到的呢,这就要和它的底层实现有关系了,实际上operator[]是调用insert实现的,而且operator[]返回的是<K,V>键值对的V的引用。

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

所以当key不存在时会将key插入map对象中,operator[]用默认的value和key组成键值对,然后插入,返回该默认的value。

如果key已经存在不会插入成功,operator[]返回已经存在的<key,vaule>键值对的value的引用。

我们可以使用insert来替代operator[]的功能,如下:

void map3()
{
	string s[] = { "西瓜", "西瓜", "菠萝", "西瓜", "苹果", "苹果", "西瓜",
		"西瓜", "菠萝", "菠萝", "哈密瓜","甜枣","甜枣","荔枝" };
	map<string, int> m;
	for (auto& e : s)
	{
		std::pair<map<string,int>::iterator, bool> it = m.insert(make_pair(e, 1));
		if (it.second == false)//key存在
		{
			++ (it.first->second);
		}
		
	}
	for (auto& e : m)
		cout << e.first << ":" << e.second << endl;

}

operator[]还可以进行增查改,例如:

void func()
{
    map<string, int> m;
    m["香蕉"];//增
	cout << m["香蕉"] << endl;//查
	m["香蕉"] = 5; //插入+修改
}

3.multiset

        它和set的用法基本相同,接口也是一致的,但是它允许冗余的键值对存在。例如:

void multiset1()
{
	multiset<int> se;
	int array[] = { 1,3,3,3,4,5,6,4 };
	for (auto& e : array)
	{
		se.insert(e);
	}
	for (auto& e : se)
		cout << e << " ";
}

4.multimap

        它和map的用法也是基本相同的,唯一的区别是multimap允许冗余的键值对存在,并且它没有operator[],因为存在多个相同的key无法区分到key值,因此不提供operator[]。

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

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

相关文章

点击编辑变完成

<template><div><button click"dialogshowtrue">添加部门</button><div>部门列表</div><el-table ref"multipleTable" :data"form" tooltip-effect"dark" style"width: 100%">&l…

roop 视频换脸

roop: one click face swap. 只用一张人脸图片&#xff0c;就能完成视频换脸。 项目地址&#xff1a; https://github.com/s0md3v/roopColab 部署&#xff1a; https://github.com/dream80/roop_colab 本文是本地部署的实践记录。 环境基础 OS: Ubuntu 22.04.2 LTSKernel: 5…

解决SVN或GIT忽略提交文件的问题

背景 使用IDEA 的SVN插件提交文件是总是会提交一些不需要提交的文件; 我们可以通过一些简单设置忽略这些文件。 git 在项目根目录新建文本文件&#xff0c;修改后缀为.gitignore 文件中添加内容 *.iml .project .gradle/ .idea/ target/ build/ .vscode/ .settings/ .facto…

Day51 算法记录| 动态规划 18(单调栈)

单调栈 739. 每日温度496.下一个更大元素 I503. 下一个更大元素 II42. 接雨水84. 柱状图中最大的矩形 单调栈&#xff1a;找最近的比他大的值 最近大的值&#xff1a;需要一个单调递减的栈&#xff08;大于栈顶元素就弹出&#xff09; 最近最小值&#xff1a;单调递减栈 方向&a…

【大数据】-- docker 启动 mysql 5.7,开启 binlog

1.说明 mysql binlog&#xff1a;二进制日志文件。它有两个作用&#xff0c;一是增量备份&#xff0c;即只备份新增的内容&#xff0c;可以用于恢复数据&#xff1b;二是用于主从复制等&#xff0c;即主节点维护了一个binlog日志文件&#xff0c;从节点从binlog中同步数据。 …

SAP-MM-采购收货操作错误的更正

业务场景: 工厂3000从供应商5555采购物料,下达采购订单时, 采购员错误操作收货101,实际为103, 收货后没有做105过账,后财务反馈未过账,采购员用MIGO+124将103冲销掉, 又重新用101收货,

助力工业物联网,工业大数据之客户回访事实指标需求分析【二十三】

文章目录 1&#xff1a;客户回访事实指标需求分析2&#xff1a;客户回访事实指标 1&#xff1a;客户回访事实指标需求分析 目标&#xff1a;掌握DWB层客户回访事实指标表的需求分析 路径 step1&#xff1a;目标需求step2&#xff1a;数据来源 实施 目标需求&#xff1a;基于客…

Redis实战(4)——Redisson分布式锁

1 基于互斥命令实现分布式锁的弊端 根据上篇文章基于redis互斥命令实现的分布式锁任然存在一定的弊端 1无法重入: 同一个线程无法重新获得同一把锁2超时删除 &#xff1a;会因为超时、任务阻塞而自动释放锁&#xff0c;出现其他线程抢占锁出现并行导致线程不安全的问题3 不可…

HTML基础介绍1

HTML是什么 1.HTML&#xff08;HyperText Mark-up Language&#xff09;即超文本标签语言&#xff08;可以展示的内容类型很多&#xff09; 2.HTML文本是由HTML标签组成的文本&#xff0c;可以包括文字、图形、动画、声音、表格、连接等 3.HTML的结构包括头部&#xff08;He…

AI绘画:当艺术遇见智能

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 前言 随着人工智能技术…

API接口给开发程序提供帮助,API接口应用价值

API可以用于开发使用相同数据的其他应用程序&#xff0c;比如公司&#xff0c;他们可以创建一个API &#xff0c;允许其他开发人员使用他们的数据并用其做其他事情&#xff0c;可以是 业务相关的 网站也可以是移动应用程序。 公司作为 信息的所有者&#xff0c; 便可以免费或收…

一次有趣的Webshell分析经历

一次有趣的Webshell分析经历 1.拉取源代码2.解密后门代码3.分析webshell逻辑4.分析404的原因5.附&#xff1a;格式化后的php代码 1.拉取源代码 在对某目标做敏感目录收集时发现对方网站备份源代码在根目录下的 backup.tar.gz&#xff0c;遂下载&#xff0c;先使用D盾分析有没有…

JS逆向-小红薯X-S环境分析

目录 前言一、分析二、验证借鉴 前言 听说这是个抓的比较严格的网址&#xff0c;这里就不作太深的分析&#xff0c;仅是将一些环境点给分析出来。 详细的可以看这位大佬的&#xff08;玩的就是一个风险转移&#xff09; 小红书x-s新版分析(2023-05-30失效) 一、分析 看波封面…

Python高阶技巧 网络编程

Socket ocket (简称 套接字) 是进程之间通信一个工具&#xff0c;好比现实生活中的插座&#xff0c;所有的家用电器要想工作都是基于插座进行&#xff0c;进程之间想要进行网络通信需要socket。 Socket负责进程之间的网络数据传输&#xff0c;好比数据的搬运工。 客户端和服务…

Element快速入门

文章目录 Element简介快速入门常见组件表格组件Pagination分页Dialog对话框Form表单 案例基本页面布局页面组件实现axios异步加载数据 vue路由打包部署 本人主攻后端&#xff0c;前端的文章基本就用来记一下的 写的文章基本没什么内容&#xff0c;还望看的多包含 Element 简介…

如何在保健品行业运用IPD?

保健品是指能调节机体功能&#xff0c;不以治疗为目的&#xff0c;并且对人体不产生任何急性、亚急性或者慢性危害的产品。保健品是食品的一个种类&#xff0c;具有一般食品的共性&#xff0c;其含有一定量的功效成分&#xff0c;能调节人体的机能&#xff0c;具有特定的功效&a…

使用Goland导出UML类图

1.安装依赖&#xff1a;goplantuml go get github.com/jfeliu007/goplantuml/parser go install github.com/jfeliu007/goplantuml/cmd/goplantumllatest 验证是否安装成功&#xff1a; 在$GOPATH的bin目录下生成.exe可执行文件&#xff1a; 2.在Goland的External Tools中添…

Java课题笔记~ MyBatis的工作流程和核心对象

一、工作流程 MyBatis的工作流程是MyBatis中重要的知识点&#xff0c;整个MyBatis工作流程分为5个步骤。 编写配置文件与映射文件&#xff1a;配置文件设置数据库连接&#xff1b;映射文件设置与SQL文件相关的操作。 MyBatis通过配置文件和映射文件生成SqlSessionFactory对象…

【第四版】 信息系统项目管理高级(高项)--第五章 信息系统工程 知识点逻辑思维导图

第五章 信息系统工程 Part1 软件工程 一、架构设计 1.软件架构目的&#xff1a;解决好软件的复用、质量、维护问题2.软件架构风格 数据流风格&#xff1a;批处理序列、管道/过滤器调用/返回风格&#xff1a;主程序/子程序独立构建风格&#xff1a;通信工程、事件驱动虚拟机风格…

年龄大了转嵌入式有机会吗?

首先&#xff0c;说下结论&#xff1a;年龄并不是限制转行嵌入式软件开发的因素&#xff0c;只要具备一定的编程和电子基础知识&#xff0c;认真学习和实践&#xff0c;是可以成为优秀的嵌入式软件开发工程师的。 1、转行建议 在转行的初期阶段&#xff0c;需要耐心学习嵌入式…