C++ STL:set和map的结构及接口使用

news2024/12/28 19:28:07

目录

一. set和map的简介

1.1 set的简介

1.2 map的简介 

二. set的主要接口函数及使用方法

2.1 构造及赋值相关接口函数

2.2 通过迭代器遍历set

2.3 结构修改相关接口函数

2.4 其他主要接口函数

三. map的主要接口函数及使用方法 

3.1 构造和赋值相关接口函数

3.2 通过迭代器遍历map

3.3 结构修改相关接口函数

3.3 查找和访问相关接口函数


一. set和map的简介

1.1 set的简介

  • set是按照一定的次序顺序存储数据的容器。
  • set的底层是通过二叉搜索树(红黑树)来实现的。
  • 在默认情况下,set底层的二叉树遵循左子节点小于根节点、右子节点大于根节点且不能有相同节点的结构要求。
  • 每个节点的值key具有const属性,不能被修改。
  • 在set中查找某个特定数据的时间复杂度是O(NlogN)。
  • 默认情况下,使用正向迭代器遍历set,是按照中序遍历进行的,也就是说会得到一组升序的数据。
  • set不可以存储相同的节点,但是multiset可以,multiset与set唯一的不同就是可以存储相同值的节点。
图1.1 set和multiset的声明

1.2 map的简介 

  • map是关联式容器。其结构与set类似,底层都是通过红黑树来实现的。
  • map和set的不同在于,map存储的数据类型是以Key和Value组成的键值对<Key, Value>,通过比较Key的值来使map满足搜索树的结构要求,而Value只是与Key进行配对的数据,不参数比较。
  • map中不允许存储两个Key相同的节点,但是multimap允许。
图1.2 map和multimap的声明

二. set的主要接口函数及使用方法

2.1 构造及赋值相关接口函数

接口函数功能
set(const compare& comp = compare)默认构造,创建空树
set(InputIterator first, InputIterator last, ...)使用迭代器区间初始化
set(const set& x)拷贝构造
set& operator=(const set& x)赋值运算符重载函数

代码2.1:(构造和赋值) 

int main()
{
	int arr[5] = { 5,2,3,4,1 };
	std::set<int> st1;   //默认构造
	std::set<int> st2(arr, arr + 5);   //迭代器区间构造
	std::set<int> st3(st2);  //拷贝构造

	std::set<int, std::greater<int>> st4;   //创建右子节点大于根节点左子节点小于根节点的set
	st1 = st3;  //赋值

	return 0;
}

2.2 通过迭代器遍历set

默认情况下,使用正向迭代器遍历set是进行中序遍历,得到一组升序的数据。

代码2.2:(set遍历的直接实现) 

int main()
{
	int arr[5] = { 5,2,3,4,1 };
	std::set<int> st1(arr, arr + 5);
	std::set<int, std::greater<int>> st2(arr, arr + 5);

	//给定迭代器
	std::set<int>::iterator it1 = st1.begin();
	std::set<int, std::greater<int>>::iterator it2 = st2.begin();

	//正向迭代器遍历st1,得到一组升序数据
	while (it1 != st1.end())
	{
		std::cout << *it1++ << " ";
	}
	std::cout << std::endl;

	//正向迭代器遍历st2,得到一组降序数据
	while (it2 != st2.end())
	{
		std::cout << *it2++ << " ";
	}
	std::cout << std::endl;

	return 0;
}
图2.1 对set前序遍历的运行结果

代码2.3:(set遍历的函数模板实现)

template<class T, class Compare = std::less<T>>
void SetPrint(const std::set<T, Compare>& st)
{
	typename std::set<T, Compare>::const_iterator it = st.begin();
	while (it != st.end())
	{
		std::cout << *it++ << " ";
	}
	std::cout << std::endl;
}

2.3 结构修改相关接口函数

接口函数功能
pair<iterator,bool> insert(const Type& x)在插入值为x的节点
void insert(InputIterator first, InputIterator last)插入位于一段迭代器区间的数据集
size_t erase(const Type& x)删除指定值
void erase(iterator pos)通过给定迭代器位置删除特定节点
void clear()清空所有节点
  • 这里需要注意insert函数的返回值:insert函数返回一键值对,pair中的first数据为iterator类型,如果成功插入节点(set中没有x),则返回新插入节点的位置的迭代器,如果插入节点失败,则返回与x值相同的节点的迭代器。pair中的second数据类型为bool,插入成功返回true,失败返回false。
  • erase返回被删除的节点的个数,因为set不允许有相同的节点,因此erase返回值只能是1或0,而multiset中erase的返回值则可以大于1,因为multiset中允许相同节点的存在。
  • 当调用erase函数给定值不存在或迭代器位置不合法时:如果使用给定值x的方法删除set的节点且x不存在,那么函数不进行任何工作,直接返回。如果给定不合法的迭代器位置调用erase,那么程序会崩溃。

代码2.4:(插入、删除和清空操作) 

int main()
{
	std::set<int> st;
	st.insert(7);
	st.insert(1);
	st.insert(0);
	st.insert(4);
	st.insert(5);   //插入数据
	SetPrint(st);   //set正向遍历打印函数

	st.erase(7);
	st.erase(10);
	st.erase(0);
	SetPrint(st);

	st.clear();   //清空元素
	SetPrint(st);

	return 0;
}
图2.2 代码2.4的运行结果

2.4 其他主要接口函数

接口函数功能
iterator find(const Type& x) const查找特定数据x函数
size_t  count(const Type& x) const统计set中x出现的次数
iterator lower_bound (const Type& x) const返回大于或等于x的最小节点
iterator upper_bound (const Type& x) const返回大于x的最小节点
pair<iterator,iterator> equal_range (const Type& x) const返回包含x的区间
  • find函数如果没有找到值为x的节点,就返回end()的迭代器位置,如果要使用find函数的返回值,保险起见,应当检查 st.find(x) != st.end() 是否成立。
  • 由于set中不允许有相同的节点,count的返回值只能是0或1。
  • equal返回的区间只包含一个数:[first, second) -- 左开右闭区间,*first = x。

代码2.5:

int main()
{
	std::set<int> st = { 10,10,20,30,40,40,50,60,70,80,90 };

	//查找数据20 -- 找得到
	std::set<int>::iterator pos1 = st.find(20);  
	if (pos1 != st.end())
	{
		std::cout << "找到了" << std::endl;
	}
	else
	{
		std::cout << "没找到" << std::endl;
	}

	//查找数据100 -- 找不到
	std::set<int>::iterator pos2 = st.find(100);
	if (pos2 != st.end())
	{
		std::cout << "找到了" << std::endl;
	}
	else
	{
		std::cout << "没找到" << std::endl;
	}

	std::set<int>::iterator it1 = st.lower_bound(30);
	std::set<int>::iterator it2 = st.lower_bound(40);
	std::set<int>::iterator it3 = st.upper_bound(40);
	std::set<int>::iterator it4 = st.upper_bound(45);

	std::cout << "*it1 = " << *it1 << std::endl;
	std::cout << "*it2 = " << *it2 << std::endl;
	std::cout << "*it3 = " << *it3 << std::endl;
	std::cout << "*it4 = " << *it4 << std::endl;

	std::pair<std::set<int>::iterator, std::set<int>::iterator> pa = st.equal_range(50);
	std::cout << "first=" << *pa.first << ", " << "second=" << *pa.second << std::endl;

	return 0;
}
图2.3 代码2.5的运行结果

三. map的主要接口函数及使用方法 

3.1 构造和赋值相关接口函数

接口函数功能
map(const compare& comp = compare)默认构造,创建空树
map(InputIterator first, InputIterator last, ...)使用迭代器区间初始化
map(const map& x)拷贝构造
map& operator=(const map& x)赋值运算符重载函数

代码3.1:(构造和赋值)

int main()
{
	std::map<int, int> mp1;  //默认构造

	std::map<int, int> rmp;
	rmp[1] = 1;
	rmp[3] = 3;
	rmp[2] = 2;

	std::map<int, int> mp2(rmp.begin(), rmp.end());  //通过迭代器区间构造
	std::map<int, int> mp3(mp2);  //拷贝构造
	mp1 = mp2;  //赋值

	return 0;
}

3.2 通过迭代器遍历map

注意:由于map存储的是键值对,对于map的迭代器it,不能直接对it解引用,*it会报错。如果想获取键值对中的数据,应当使用(*it).first/second 或it->first/second。

代码3.1:(迭代器遍历map)

int main()
{
	std::map<int, int> mp;
	mp[1] = 1;
	mp[3] = 3;
	mp[2] = 2;

	std::map<int, int>::iterator it = mp.begin();
	while (it != mp.end())
	{
		//std::cout << (*it).first << "=>" << (*it).second << " ";
		std::cout << it->first << "=>" << it->second << " ";
		++it;
	}
	std::cout << std::endl;

	return 0;
}
图3.2 代码3.1的运行结果

3.3 结构修改相关接口函数

接口函数功能
pair<iterator,bool> insert(const pair<T1,T2>& x)数据插入函数
void insert(InputIterator first, InputIterator second)插入某段迭代器区间的数据
size_t erase(const Type_Key& x)删除键值对中Key为x的数据
void erase(iterator pos)删除特定迭代器位置的节点
void erase(iterator first, iterator second)删除特定迭代器区间的节点
void clear()清空元素
  • make_pair(const Type1& key, const Type2& value) -- 键值对创建函数,给定参数为键值对的key和value,返回键值对pair<Type1,Type2>

代码3.2:(结构修改)

int main()
{
	std::map<int, int> mp;
	mp.insert(std::make_pair(5, 5));
	mp.insert(std::make_pair(7, 7));
	mp.insert(std::make_pair(3, 3));
	mp.insert(std::make_pair(1, 1));
	mp.insert(std::make_pair(9, 9));   //插入数据

	std::map<int, int>::iterator it = mp.begin();
	while (it != mp.end())
	{
		std::cout << it->first << "=>" << it->second << " ";
		++it;
	}
	std::cout << std::endl;

	mp.erase(1);
	mp.erase(9);  //给定值删除
	mp.erase(mp.begin());  //给定迭代器位置删除

	it = mp.begin();
	while (it != mp.end())
	{
		std::cout << it->first << "=>" << it->second << " ";
		++it;
	}
	std::cout << std::endl;

	mp.clear();  //清空元素

	return 0;
}
图3.3 代码3.2的运行结果

3.3 查找和访问相关接口函数

接口函数功能
iterator find(const Key_Type x)查找键值对Key为x的节点
Value_Type& operator[](const Key_Type x)

通过指定的Key的值x访问与之配对的Value值

/ 创建Key值为x的新节点

  • operator[]函数:如果在二叉map中找到了x,那么就直接返回与之配对的Value值的引用。如果没有找到x,那么就会以x为Key插入新的节点,但是Value的值就只能调用的类型的默认构造来给初值,无法保证新插入的节点的Value初值是需要的。

代码3.3:(查找和访问)

int main()
{
	std::map<int, int> mp;
	mp.insert(std::make_pair(5, 5));
	mp.insert(std::make_pair(7, 7));
	mp.insert(std::make_pair(3, 3));
	mp.insert(std::make_pair(1, 1));
	mp.insert(std::make_pair(9, 9));   

	std::map<int, int>::iterator it = mp.find(3);
	std::cout << it->first << "=>" << it->second << std::endl;

	mp[3] = 5;  //3存在
	std::cout << "mp[3] = " << mp[3] << std::endl;

	mp[10] = 10;   //10不存在
	std::cout << "mp[10] = " << mp[10] << std::endl;

	return 0;
}
图3.4 代码3.3的运行结果

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

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

相关文章

Midjourney放大招,什么好看唯美高清,统统都是我的

你知道吗&#xff1f;超过99%的人都没有足够出色的肖像照来展现自己的魅力&#xff0c;除非你是那种在网上拥有成千上万张自己肖像照的大明星。但是&#xff0c;好消息来了&#xff01;现在有一个InsightFaceSwap Discord bot&#xff0c;可以帮助你实现这个“不可能完成”的想…

【JavaEE初阶】多线程进阶(五)常见锁策略 CAS synchronized优化原理

文章目录 常见锁策略乐观锁 & 悲观锁轻量级锁 & 重量级锁自旋锁 & 挂起等待锁互斥锁 & 读写锁公平锁 & 非公平锁可重入锁 & 不可重入锁synchronized对应以上的锁策略锁策略中的面试题&#xff1a; CASCAS的介绍CAS如何实现CAS的应用场景CAS的典型问题&…

Excel公式:将日期转换为月份年

Excel公式&#xff1a;将日期转换为月份年 在Excel中&#xff0c;您可以将日期单元格格式化为多种类型的日期格式&#xff0c;但是在某些情况下&#xff0c;您希望将日期转换为文本格式&#xff0c;仅转换为月&#xff0c;年&#xff0c;日或月年&#xff0c;日月或年日。 在本…

Java全栈学习路线总结,科班程序员搬砖逆袭

&#x1f307;文章目录 前言一、前置知识二、 Web前端基础示例&#xff1a;1.文本域2.密码字段 三、后端基础一. Java基础二. 数据库技术三. Web开发技术四. 框架技术五. 服务器部署 四、其他技术五、全栈开发六、综合实践七、学习教程一、前端开发二、后端开发三、数据库开发四…

VUE 学习笔记(三) Vue 渲染流程详解

在 Vue 里渲染一块内容&#xff0c;会有以下步骤及流程&#xff1a; 第一步&#xff0c;解析语法&#xff0c;生成AST 第二步&#xff0c;根据AST结果&#xff0c;完成data数据初始化 第三步&#xff0c;根据AST结果和DATA数据绑定情况&#xff0c;生成虚拟DOM 第四步&…

ESP32设备驱动-Si1145红外接近-紫外 (UV) 指数和环境光传感器驱动

Si1145红外接近-紫外 (UV) 指数和环境光传感器驱动 文章目录 Si1145红外接近-紫外 (UV) 指数和环境光传感器驱动1、Si1145介绍2、硬件准备3、软件准备4、驱动实现1、Si1145介绍 Si1145/46/47 是一款低功耗、基于反射的红外接近、紫外 (UV) 指数和环境光传感器,具有 I2C 数字接…

电脑百度网盘打不开怎么办 电脑百度网盘双击没反应处理方法

有时候我们想要在电脑浏览器上下载一些文件时&#xff0c;打开的文件下载链接有些需要通过百度网盘来存储下载&#xff0c;然而当用户在电脑中安装完百度网盘工具之后&#xff0c;双击想要打开时却总是没反应&#xff0c;对此电脑百度网盘打不开怎么办呢&#xff1f;接下来小编…

Java反射和动态代理

反射 反射允许对封装类的成员变量、成员方法和构造方法的信息进行编程访问 成员变量&#xff1a;修饰符、名字、类型、get/set值 构造方法&#xff1a;修饰符、名字、形参、创建对象 成员方法&#xff1a;修饰符、名字、形参、返回值、抛出的异常、获取注解、运行方法 获取…

【云原生进阶之PaaS中间件】第一章Redis-1.1简介

1 Redis概述 1.1 Redis 简介 Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API&#xff0c;可用作数据库&#…

高质量毕业答辩PPT模板+PPT网站

文章目录 前言一、iSlide二、office plus三、优品PPT总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 又是一年毕业季&#xff0c;又到了快要答辩的时候&#xff0c;最近有一些小伙伴找我要毕业答辩PPT模板&#xff0c;本着这不能拒绝啊的心态&…

20230507使用python3批量转换DOCX文档为TXT

20230507使用python3批量转换DOCX文档为TXT 2023/5/7 20:22 WIN10使用python3.11 # – coding: gbk – import os from pdf2docx import Converter from win32com import client as wc """这里需要安转包pywin32com""" # 读取pdf文件文本内容 …

探秘二分查找中的数学奇迹:如何手动求解整数x的平方根

本篇博客会讲解力扣“69. x 的平方根”这道题的解题思路。这是题目链接。 大家先来审下题&#xff1a; 以及示例&#xff1a; 还有提示&#xff1a; 本题常规的思路有&#xff1a;暴力查找、转换成指数和对数、二分查找、牛顿迭代。 转换成指数和对数的方法非常简单&#…

接口自动化测试框架9项必备功能有哪些?你一定不知道

当你准备使用一个接口测试框架或者自造轮子的时候&#xff0c;或许你需要先了解下一个接口自动化测试框架必须具备什么功能。 一、校验   这个很好了解&#xff0c;如果没有校验&#xff0c;单纯的执行接口的话&#xff0c;那就谈不上测试了。所以支持对返回值校验是一个必须…

[Golang] 爬虫实战-获取动态页面数据-获取校招信息

&#x1f61a;一个不甘平凡的普通人&#xff0c;致力于为Golang社区和算法学习做出贡献&#xff0c;期待您的关注和认可&#xff0c;陪您一起学习打卡&#xff01;&#xff01;&#xff01;&#x1f618;&#x1f618;&#x1f618; &#x1f917;专栏&#xff1a;算法学习 &am…

Solr(1):Solr概述

1 概述 Solr 是一个基于 Apache Lucene 之上的搜索服务器&#xff0c;它是一个开源的、基于 Java 的信息检索库。它旨在驱动功能强大的文档检索应用程序 - 无论您需要根据用户的查询将数据服务到何处&#xff0c;Solr 都可以为您服务。Solr与应用程序的集成以为您服务。 下面…

es 7.x 通过DSL语句添加doc数据

一 在es中doc数据的crud操作 1.1 说明 本案例操作 接上一篇的基础上进行操作。 1.2 添加doc 方式为post http://localhost:9200/order_item/_doc 添加文档数据 必须是post提交&#xff0c;不能是put 1.3 查看文档数据 http://localhost:9200/order_item/_doc/_searc…

118-Linux_数据库_索引

文章目录 一.索引是什么?二.索引为什么选择b树三.测试索引1.在mysql中创建数据库 test_indexdb2.在test_indexdb中创建表 test_index3.运行程序向表中插入1万条数据&#xff0c;都是字符串4. 查询验证 一.索引是什么? 索引是一种特殊的文件&#xff0c;它包含着对数据表里所…

浅谈osgEarth操控器类的createLocalCoordFrame函数如何将局部坐标系的点转为世界坐标系下的Martix(ENU坐标)

在osgEarth操控器类的EarthManipulator中的如下函数&#xff1a; void EarthManipulator::setLookAt(const osg::Vec3d& center,double azim,double pitch,double range,const osg::Vec3d& posOffset) {setCenter( center );.... //…

二、PEMFC基础之电化学与反应动力学

二、PEMFC基础之电化学与反应动力学 1.电流、电流密度2.反应速率常数3.交换电流密度4.电化学动力学奠基石B-V方程5.活化损失计算Tafel公式6.计算案例 1.电流、电流密度 由法拉第定律 i d Q d t n F d N d t i\frac{dQ}{dt}\frac{nFdN}{dt} idtdQ​dtnFdN​ j i A j\frac{…

查询缓存实现、缓存更新策略选择、解决缓存穿透缓存雪崩缓存击穿问题

文章目录 1 什么是缓存?1.1 为什么要使用缓存1.2 如何使用缓存 2 给商户信息查询业务添加缓存2.1 缓存模型和思路2.2 代码如下 3 缓存更新策略3.1 数据库缓存不一致解决方案&#xff1a;3.2 数据库和缓存不一致采用什么方案3.3 删除缓存还是更新缓存&#xff1f;3.4 如何保证缓…