C++之STL整理(4)之set 用法(创建、赋值、增删查改)详解
C++之STL整理(4)之set 用法(创建、赋值、增删查改)详解
注:整理一些突然学到的C++知识,随时mark一下
例如:忘记的关键字用法,新关键字,新数据结构
C++ 的map用法整理
- C++之STL整理(4)之set 用法(创建、赋值、增删查改)详解
- 一、set的初始化
- 1、set初始化
- (1)构造函数初始化
- (2)赋值操作
- (3)swap函数;
- 3、大小操作
- 二、set的增删查改
- 1、插入操作insert
- 2、删操作erase、clear
- 3、查找操作 find
- 4、统计count
- 三、指定排序规则
- 1、指定set容器的排序规则
- 2、 对于自定义数据类型,set 必须指定排序规则
- 总结
提示:本文为 C++ 中 set构造、赋值、接口 的写法和举例
一、set的初始化
STL 中的set是一个关联容器,它存储的元素都是键值一体的(key-value pair),并且也会根据键(key)自动排序。set存储的元素(键)是唯一的,不允许键重复,并且默认按照从小到大的顺序进行排序(和map一样也可以通过提供一个自定义的比较函数或对象来改变排序方式,自定义类型必须增加)。std::set 的元素通过其键或迭代器进行访问,并且在这个容器中,键也是值(key is value),也就是说set相当于键值一体的map。
set的基本操作
插入元素:使用 insert
成员函数向 set 中插入元素。如果元素已经存在,则不会插入重复的元素。.insert()
的返回值是个pair结构的对组 pair<iterator, bool>
bool代表插入是否成功。
查找元素:使用 find
成员函数来查找元素。如果找到元素,则返回指向该元素的迭代器;否则返回 end() 迭代器。
删除元素:使用 erase
成员函数来删除元素。你可以通过迭代器或键来删除元素。
遍历元素:使用迭代器iterato
r来遍历 set 中的元素。由于 set 是有序的,所以遍历将按照元素的排序顺序进行。
示例
下面是一个简单的 std::set 使用示例:
#include <iostream>
#include <set> int main() { std::set<int> mySet; // 插入元素 mySet.insert(3); mySet.insert(1); mySet.insert(4); mySet.insert(1); // 不会插入重复的元素 // 遍历并打印元素 for (int num : mySet) { std::cout << num << " "; } std::cout << std::endl; // 输出: 1 3 4 // 查找元素 if (mySet.find(3) != mySet.end()) { std::cout << "Found 3 in the set." << std::endl; } // 删除元素 mySet.erase(4); // 再次遍历并打印元素 for (int num : mySet) { std::cout << num << " "; } std::cout << std::endl; // 输出: 1 3 return 0;
}
性能特点
插入和删除操作:由于 std::set 是基于红黑树实现的,所以插入和删除操作的平均时间复杂度为 O(log n)
,其中 n 是集合中元素的数量。
查找操作:查找操作的平均时间复杂度也是 O(log n)
。
内存使用:set 通常需要比数组或向量更多的内存,因为它需要存储额外的信息来维护树的平衡。
1、set初始化
(1)构造函数初始化
set<T> st;
和 multiset<T> mst;
这两个是默认构造函数,用于创建一个空的 set 或 multiset。
示例:
std::set<int> mySet; // 创建一个空的整数set
std::multiset<std::string> myMultiSet; // 创建一个空的字符串multiset
set(const set &st);
和 multiset(const multiset &mst);
这些是拷贝构造函数,用于创建一个新的 set 或 multiset,它是现有 set 或 multiset 的副本。
示例:
std::set<int> mySet = {1, 2, 3};
std::set<int> anotherSet(mySet); // 创建一个mySet的副本
(2)赋值操作
set& operator=(const set &st); 和 multiset& operator=(const multiset &mst);
是重载的等号操作符,用于将一个 set 或 multiset 的内容赋值给另一个已经存在的 set 或 multiset。
示例:
std::set<int> mySet = {1, 2, 3};
std::set<int> anotherSet;
anotherSet = mySet; // 将mySet的内容赋给anotherSet
(3)swap函数;
swap 是一个成员函数,用于交换两个 set 或 multiset 的内容。
std::set<int> mySet = {1, 2, 3};
std::set<int> anotherSet = {4, 5, 6};
mySet.swap(anotherSet); // 交换两个set的内容
3、大小操作
成员函数size();
返回 set 或 multiset 中元素的数量。
成员函数empty();
判断 set 或 multiset 是否为空。如果为空,返回 true;否则返回 false。
示例:
std::set<int> mySet = {1, 2, 3, 4, 5};
std::cout << "Size of mySet: " << mySet.size() << std::endl; // 输出: Size of mySet: 5std::set<int> mySet;
if (mySet.empty()) { std::cout << "mySet is empty." << std::endl;
} else { std::cout << "mySet is not empty." << std::endl;
} // 输出: mySet is empty.
二、set的增删查改
1、插入操作insert
insert(elem);
用于在 set 或 multiset 中插入一个元素。如果元素已存在(对于 set),则不会重复插入。
std::set<int> mySet;
mySet.insert(5); // 插入元素5
mySet.insert(3); // 插入元素3
2、删操作erase、clear
clear();
清除 set 或 multiset 中的所有元素。
erase(pos);
删掉迭代器 pos 所指向的元素,并返回指向下一个元素的迭代器。
std::set<int> mySet = {1, 2, 3, 4, 5};
auto it = mySet.find(3); // 查找元素3的迭代器
if (it != mySet.end()) { it = mySet.erase(it); // 删除元素3,it现在指向4
}
mySet.clear(); // 清空set,现在mySet是空的
erase(beg, end);
删除区间 [beg, end) 内的所有元素,并返回指向 end 之后元素的迭代器。
std::set<int> mySet = {1, 2, 3, 4, 5};
auto it = mySet.find(3); // 查找元素3的迭代器
if (it != mySet.end()) { mySet.erase(it, std::next(it)); // 删除元素3(包括3)之后的所有元素
}
erase(elem);
删除容器中值为 elem 的元素。对于 set,这只会删除一个元素(如果存在的话),因为 set 中的元素是唯一的。对于 multiset,会删除所有值为 elem 的元素。
std::multiset<int> myMultiSet = {1, 2, 2, 3, 4, 4, 4};
myMultiSet.erase(2); // 删除一个值为2的元素
myMultiSet.erase(4); // 删除一个值为4的元素,现在myMultiSet中还有两个4
3、查找操作 find
find(key);
在 set 或 multiset 中查找键 key。如果找到,返回指向该键的元素的迭代器;否则返回 end() 迭代器。
std::set<int> mySet = {1, 2, 3, 4, 5};
auto it = mySet.find(3); // 查找元素3
if (it != mySet.end()) { std::cout << "Found: " << *it << std::endl; // 输出: Found: 3
} else { std::cout << "Not found." << std::endl;
}
4、统计count
count(key);
对于 set,由于元素是唯一的,count(key) 要么返回 1(如果 key 存在),要么返回 0(如果 key 不存在)。对于 multiset,它返回 key 出现的次数。
std::multiset<int> myMultiSet = {1, 2, 2, 3, 4, 4, 4};
size_t countOfTwo = myMultiSet.count(2); // 查找元素2出现的次数
std::cout << "Number of 2s: " << countOfTwo << std::endl; // 输出: Number of 2s: 2
三、指定排序规则
您提到的内容是关于std::set和std::multiset容器的一个重要特性,即可以自定义排序规则。默认情况下,这些容器使用std::less来比较元素,但是可以通过提供自定义的比较函数或仿函数(functor)来改变排序规则。
1、指定set容器的排序规则
创建set或multiset时指定排序规则通常是通过传递一个比较对象(比如函数对象或lambda表达式)给容器的构造函数(第二个参数)来实现的。这个比较对象必须满足比较函数的要求,假设对于任何两个类型T的对象a和b,比较对象comp有以下规则条件:
comp(a, b)在a小于b时返回true
comp(b, a)在b小于a时返回true
comp(a, a)对于任何a都返回false
示例:
#include <iostream>
#include <set>
#include <string> // 自定义比较函数对象
struct MyCompare { bool operator()(const std::string& a, const std::string& b) const { // 这里我们按照字符串的长度进行排序,而不是默认的字典序 return a.size() < b.size(); }
}; int main() { // 使用自定义比较对象创建set std::set<std::string, MyCompare> mySet; // 插入元素,它们将按照字符串长度排序 mySet.insert("apple"); mySet.insert("banana"); mySet.insert("cherry"); // 输出set中的元素,将看到它们按长度排序 for (const auto& str : mySet) { std::cout << str << ' '; } std::cout << std::endl; return 0;
}
2、 对于自定义数据类型,set 必须指定排序规则
当使用自定义数据类型作为set或multiset的键时,通常需要提供一个比较函数或仿函数来定义如何比较这些对象。这是因为std::set和std::multiset需要知道这个新数据类型如何对元素进行排序。
示例:
假设我们有一个自定义的Person
类,我们想要根据年龄对Person对象进行排序:
#include <iostream>
#include <set>
#include <string> // 自定义数据类型
struct Person { std::string name; int age; Person(const std::string& name, int age) : name(name), age(age) {}
}; // 自定义比较函数对象,用于Person类型的set
struct PersonCompare { bool operator()(const Person& a, const Person& b) const { return a.age < b.age; // 按照年龄升序排序 }
}; int main() { // 使用自定义比较对象创建set来存储Person对象 std::set<Person, PersonCompare> peopleSet; // 插入Person对象 peopleSet.insert(Person("Alice", 30)); peopleSet.insert(Person("Bob", 20)); peopleSet.insert(Person("Charlie", 25)); // 输出set中的Person对象,将看到它们按年龄排序 for (const auto& person : peopleSet) { std::cout << person.name << ": " << person.age << std::endl; } return 0;
}
在这个例子中,我们定义了一个PersonCompare仿函数来告诉set如何比较Person对象。这样,当我们将Person对象插入到set中时,它们将按照年龄进行排序。
总结
相关文章:
C++之STL整理(4)之set 用法(创建、赋值、增删查改)详解
C之STL整理(4)之set 用法(创建、赋值、增删查改)详解 注:整理一些突然学到的C知识,随时mark一下 例如:忘记的关键字用法,新关键字,新数据结构 C 的map用法整理 C之STL整理…...

IDEA MyBatisCodeHelper Pro最新版(持续更新)
目录 0. 你想要的0.1 包下载0.2 使用jh 1. 功能介绍2. 下载安装2.1 在idea中插件市场安装2.2 在jetbrains插件市场下载安装 3. 简单使用3.1 创建一个SpringBoot项目3.2 配置数据库3.3 一键生成实体类、mapper 0. 你想要的 0.1 包下载 测试系统:Windows(…...

sheng的学习笔记-AI-YOLO算法,目标检测
AI目录:sheng的学习笔记-AI目录-CSDN博客 目录 目标定位(Object localization) 定义 原理图 具体做法: 输出向量 图片中没有检测对象的样例 损失函数 编辑 特征点检测(Landmark detection) 定义&a…...

C# wpf 嵌入wpf控件
WPF Hwnd窗口互操作系列 第一章 嵌入Hwnd窗口 第二章 嵌入WinForm控件 第三章 嵌入WPF控件(本章) 第四章 底部嵌入HwndHost 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现?1、继承HwndHost2、添加Content属性3、创建wpf窗口并设置Conten…...

云原生(六)、CICD - Jenkins快速入门
Jenkuns快速入门 一、CICD概述 CICD是持续集成(Continuous Integration)和持续部署(Continuous Deployment)的缩写。它是软件开发中的一种流程和方法论,旨在通过自动化的方式频繁地将代码集成到共享存储库中…...

基于java+springboot+vue实现的付费自习室管理系统(文末源码+Lw+ppt)23-400
摘 要 付费自习室管理系统采用B/S架构,数据库是MySQL。网站的搭建与开发采用了先进的java进行编写,使用了springboot框架。该系统从两个对象:由管理员和用户来对系统进行设计构建。主要功能包括:个人信息修改,对用户…...
【JavaParser笔记02】JavaParser解析Java源代码中的类字段信息(javadoc注释、字段名称)
这篇文章,主要介绍如何使用JavaParser解析Java源代码中的类字段信息(javadoc注释、字段名称)。 目录 一、JavaParser依赖库 1.1、引入依赖 1.2、获取类成员信息 (1)案例代码 <...

Spring IoCDI(3)
DI详解 接下来学习一下依赖注入DI的细节. 依赖注入是一个过程, 是指IoC容器在创建Bean时, 去提供运行时所依赖的资源, 而资源指的就是对象. 在之前的案例中, 使用了Autowired这个注解, 完成了依赖注入这个操作. 简单来说, 就是把对象取出来放到某个类的属性中. 在一些文章中…...
保研线性代数机器学习基础复习1
1.什么是代数(algebra)? 为了形式化一个概念,构建出有关这个概念的符号以及操作符号的公式。 2.什么是线性代数(linear algebra)? 一项关于向量以及操作向量的公式的研究。 3.举一些向量的例子&#x…...
js绑定事件的方法
在JavaScript中,绑定事件的方法主要有以下几种: HTML属性方式:直接在HTML元素中使用事件属性来绑定事件。 html<button onclick"alert(Hello World!)">Click Me</button> DOM属性方式:通过JavaScript代码…...

是德科技keysight N9000B 信号分析仪
181/2461/8938产品概述: 工程的内涵就是将各种创意有机地联系起来,并解决遇到的问题。 CXA 信号分析仪具有出色的实际性能,它是一款出类拔萃、经济高效的基本信号表征工具。 它的功能十分强大,为一般用途和教育行业的用户执行测试…...
软考 - 系统架构设计师 - 架构风格
软件架构风格是指描述特定软件系统组织方式的惯用模式。组织方式描述了系统的组成构件,以及这些构件的组织方式,惯用模式指众多系统所共有的结构和语义。 目录 架构风格 数据流风格 批处理架构风格 管道 - 过滤器架构风格 调用 / 返回风格 主程序…...

CleanMyMac X2024专业免费的国产Mac笔记本清理软件
非常高兴有机会向大家介绍CleanMyMac X 2024这款专业的Mac清理软件。它以其强大的清理能力、系统优化效果、出色的用户体验以及高度的安全性,在Mac清理软件市场中独树一帜。 CleanMyMac X2024全新版下载如下: https://wm.makeding.com/iclk/?zoneid49983 一、主要…...
ES6 模块化操作
ES6模块化主要有两个操作:import 和 export 如果在html文件的script中引用模块的话,要设置<script type"module"> 一种导入导出方法: a.js//分别暴露 export let num 1 export function compute(a, b){return a b }//统…...

统计XML文件内标签的种类和其数量及将xml格式转换为yolov5所需的txt格式
1、统计XML文件内标签的种类和其数量 对于自己标注的数据集,需在标注完成后需要对标注好的XML文件校验,下面是代码,只需将SrcDir换成需要统计的xml的文件夹即可。 import os from tqdm import tqdm import xml.dom.minidomdef ReadXml(File…...

《操作系统导论》第14章读书笔记:插叙:内存操作API
《操作系统导论》第14章读书笔记:插叙:内存操作API —— 杭州 2024-03-30 夜 文章目录 《操作系统导论》第14章读书笔记:插叙:内存操作API1.内存类型1.1.栈内存:它的申请和释放操作是编译器来隐式管理的,所…...

HAProxy + Vitess负载均衡
一、环境搭建 Vitess环境搭建: 具体vitess安装不再赘述,主要是需要启动3个vtgate(官方推荐vtgate和vtablet数量一致) 操作: 在vitess/examples/common/scripts目录中,修改vtgate-up.sh文件,…...

2024年京东云主机租用价格_京东云服务器优惠价格表
2024年京东云服务器优惠价格表,轻量云主机优惠价格5.8元1个月、轻量云主机2C2G3M价格50元一年、196元三年,2C4G5M轻量云主机165元一年,4核8G5M云主机880元一年,游戏联机服务器4C16G配置26元1个月、4C32G价格65元1个月、8核32G费用…...

qt-C++笔记之QSpinBox控件
qt-C笔记之QSpinBox控件 code review! 文章目录 qt-C笔记之QSpinBox控件1.运行2.main.cpp3.main.pro4.《Qt6 C开发指南》:4.4 QSpinBox 和QDoubleSpinBox 1.运行 2.main.cpp #include <QApplication> #include <QSpinBox> #include <QPushButton&g…...

Linux(CentOS)/Windows-C++ 云备份项目(服务器网络通信模块,业务处理模块设计,断点续传设计)
此模块将网络通信模块和业务处理模块进行了合并 网络通信通过httplib库搭建完成业务处理: 文件上传请求:备份客户端上传的文件,响应上传成功客户端列表请求:客户端请求备份文件的请求页面,服务器响应文件下载请求&…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...