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库搭建完成业务处理: 文件上传请求:备份客户端上传的文件,响应上传成功客户端列表请求:客户端请求备份文件的请求页面,服务器响应文件下载请求&…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...