【C++】set详解

news2024/12/28 11:40:50

📢博客主页:https://blog.csdn.net/2301_779549673
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 JohnKi 原创,首发于 CSDN🙉
📢未来很长,值得我们全力奔赴更美好的生活✨

在这里插入图片描述

在这里插入图片描述

文章目录

  • 📢前言
  • 🏳️‍🌈 一、set类的介绍
  • 🏳️‍🌈二、set的构造和迭代器
  • 🏳️‍🌈三、set的增删查
  • 🏳️‍🌈四、insert和迭代器遍历使用样例
  • 👥总结


📢前言

Set 是 C++ 标准模板库(STL)中的一种关联容器,主要用于存储不重复且有序的元素。其内部实现采用红黑树,这种数据结构具有自动排序的特性,能够高效地进行插入、删除和查找操作。

红黑树是一种平衡二叉搜索树,它的统计性能优于一般的平衡二叉树。在 set 中,每个元素的值都唯一,并且元素的值不能直接被改变。这是因为 set 中的元素值就是其键值,关系到 set 元素的排列规则。如果任意改变 set 的元素值,会严重破坏 set 的组织。

Set 的迭代器被定义为底层红黑树的 const_iterator,杜绝了写入操作。这意味着我们不能通过 set 的迭代器直接修改元素的值。例如,当我们尝试通过 set 的迭代器改变元素的值时,编译器会报错。

此外,当对 set 进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后都依然有效,被删除的那个元素的迭代器必然是个例外。这种特性使得 set 在进行动态操作时,能够保持迭代器的有效性,方便了程序的编写和维护。

总的来说,C++ 中的 set 容器以其独特的特性和高效的内部实现,为程序员提供了一种方便、可靠的数据存储和操作方式。


🏳️‍🌈 一、set类的介绍

  • set的声明如下,T就是set底层关键字的类型.
  • set默认要求T支持小于比较,如果不支持或者想按自己的需求走可以自行实现仿函数传给第二个模版参数
  • set底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第三个参数。
  • 一般情况下,我们都不需要传后两个模版参数。
  • set底层是用红黑树实现,增删查效率是O(l0gN),迭代器遍历是走的搜索树的中序,所以是有序的。
  • 前面部分我们已经学习了vector/list等容器的使用,STL容器接口设计,高度相似,所以这里我们就不再一个接口一个接口的介绍,而是直接带着大家看文档,挑比较重要的接口进行介绍。
template < class T, // set::key_type/value_type
           class Compare = less<T>, // set::key_compare/value_compare
           class Alloc = allocator<T> // set::allocator_type
           > class set;

🏳️‍🌈二、set的构造和迭代器

  • set的构造我们关注以下几个接口即可。
  • set的支持正向和反向迭代遍历,遍历默认按升序顺序,因为底层是二叉搜索树,迭代器遍历走的中序;支持迭代器就意味着支持范围for,set的iterator和const iterator都不支持迭代器修改数据,修改关键字数据,破坏了底层搜索树的结构。

Set 的构造方式主要有以下几种:
默认构造函数:set st;,创建一个空的 set。例如:set mySet;。
拷贝构造函数:set(const set &st);,创建一个新的 set,它是现有 set 的副本。例如:set mySet = {1, 2, 3}; set anotherSet(mySet);。
使用区间构造:可以用一个已有的区间中的元素构造 set,如set s2(s1.begin(), s1.end());。
赋值操作可以使用重载的等号操作符:set& operator=(const set &st);,将一个 set 的内容赋值给另一个已经存在的 set。例如:set mySet = {1, 2, 3}; set anotherSet; anotherSet = mySet;。

// empty (1) ⽆参默认构造
explicit set (const key_compare& comp = key_compare(),
              const allocator_type& alloc = allocator_type());
// range (2) 迭代器区间构造
template <class InputIterator>
set (InputIterator first, InputIterator last,
     const key_compare& comp = key_compare(),
     const allocator_type& = allocator_type());
// copy (3) 拷⻉构造
set (const set& x);
// initializer list (5) initializer 列表构造
set (initializer_list<value_type> il,
     const key_compare& comp = key_compare(),
     const allocator_type& alloc = allocator_type());
// 迭代器是⼀个双向迭代器
iterator -> a bidirectional iterator to const value_type
// 正向迭代器
iterator begin();
iterator end();
// 反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();

🏳️‍🌈三、set的增删查

set的增删查关注以下几个接口即可:

  • 插入元素
    使用insert方法可以在 set 中插入元素。例如:mySet.insert(5);。如果元素已存在,插入操作将被忽略。insert方法的返回值是个pair结构的对组,pair<iterator, bool>,bool 代表插入是否成功。当向 set 容器添加元素成功时,该迭代器指向 set 容器新添加的元素,bool 类型的值为 true;如果添加失败,即证明原 set 容器中已存有相同的元素,此时返回的迭代器就指向容器中相同的此元素,同时 bool 类型的值为 false。
  • 查找元素
    使用find方法查找 set 中元素。例如:auto it = mySet.find(element);,如果找到元素,it将指向该元素;否则,it将指向 set 的尾后。可以通过判断it是否等于end()来确定元素是否被找到。
  • 删除元素
    使用erase方法删除 set 中元素,有以下几种方式:
    删除迭代器指向的元素:erase(pos);,例如:auto it = mySet.find(3); if(it!= mySet.end()){ it = mySet.erase(it); }。
    删除指定值的元素:erase(elem);,例如:mySet.erase(4);。
    删除区间内的元素:erase(beg, end);。
  • 其他方法
    size():返回 set 中元素的数目。
    empty():判断 set 是否为空。如果为空,返回 true;否则返回 false。
    clear():清空 set 中的所有元素。
    lower_bound():返回大于或等于给定元素的第一个元素的迭代器。
    upper_bound():返回大于给定元素的第一个元素的迭代器。
    equal_range():返回一组迭代器,表示给定元素在 set 中的范围。
Member types
key_type -> The first template parameter (T)
value_type -> The first template parameter (T)
// 单个数据插⼊,如果已经存在则插⼊失败
pair<iterator, bool> insert (const value_type& val);
// 列表插⼊,已经在容器中存在的值不会插⼊
void insert (initializer_list<value_type> il);
// 迭代器区间插⼊,已经在容器中存在的值不会插⼊
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
// 查找val,返回val所在的迭代器,没有找到返回end()
iterator find (const value_type& val);
// 查找val,返回Val的个数
size_type count (const value_type& val) const;
// 删除⼀个迭代器位置的值
iterator erase (const_iterator position);
// 删除val,val不存在返回0,存在返回1
size_type erase (const value_type& val);
// 删除⼀段迭代器区间的值
iterator erase (const_iterator first, const_iterator last);
// 返回⼤于等val位置的迭代器
iterator lower_bound (const value_type& val) const;
// 返回⼤于val位置的迭代器
iterator upper_bound (const value_type& val) const;

易错点提示
end()函数的正确用法:end()函数的作用不是用于返回最后一个元素,而是用于返回 set 中最后一个元素的后一个位置的指针。如果一个 set 中的元素是<1,2,3>,那么返回的就是元素 3 之后的一位的指针。如果要看最后一个元素,可以使用遍历的方式找到最后一个元素,或者使用其他方法。

不能直接 copy:不能将一个 set 直接使用=号赋值给另外一个 set。如下面的写法就是错误的:set set1; set set2 = set1;。这种写法会导致编译错误或者不可预期的结果。在 C++ 中,set 的赋值操作需要使用特定的方法,如拷贝构造函数或者赋值运算符重载。

🏳️‍🌈四、insert和迭代器遍历使用样例

#include<iostream>
#include<set>
using namespace std;
int main() {
// 去重+升序排序
    set<int> s;
// 去重+降序排序(给⼀个⼤于的仿函数)
//set<int, greater<int>> s;
    s.insert(5);
    s.insert(2);
    s.insert(7);
    s.insert(5);
//set<int>::iterator it = s.begin();
    auto it = s.begin();
    while (it != s.end()) {
        // error C3892: “it”: 不能给常量赋值
// *it = 1;
        cout << *it << " ";
        ++it;
    }
    cout << endl;
// 插⼊⼀段initializer_list列表值,已经存在的值插⼊失败
    s.insert({ 2, 8, 3, 9 });
    for (auto e : s) {
        cout << e << " ";
    }
    cout << endl;
    set<string> strset = { "sort", "insert", "add" };
// 遍历string⽐较ascll码⼤⼩顺序遍历的
    for (auto& e : strset) {
        cout << e << " ";
    }
    cout << endl;
}

👥总结


本篇博文对 set 做了一个较为详细的介绍,不知道对你有没有帮助呢

觉得博主写得还不错的三连支持下吧!会继续努力的~

请添加图片描述

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

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

相关文章

对异步处理的http接口进行性能测试

最近来了新的领导&#xff0c;测试的内容和范畴都变大了&#xff0c;工作内容涉及到APP&#xff0c;线上出现了由于性能引起的bug&#xff0c;不得不进行压测&#xff0c;只能不断的学习了。害&#xff0c;想做一条咸鱼都那么难&#xff0c;找了很多关于接口性能测试的资料&…

模板初阶、auto关键字、范围for和string类的使用

目录 1. 模板初阶 1.1 泛型编程 1.2 函数模板 1.3 类模板 2. auto关键字 3. 范围for的使用&#xff08;略提&#xff09; 4. String类部分接口的使用 4.1 String构造函数的使用 4.2 string类begin和end的使用 4.3 string类的rbegin和rend的使用 4.4 string类的size和length的使…

使用 npkill 快速清理本地 node_modules 文件

npkill 可以直接在终端可视化的清除 本地 node_modules 文件夹&#xff0c;方便我们即使清除不常用的依赖。 直接在终端执行 npx npkill 即可开启 node_modules 本地扫描&#xff1a; 然后&#xff0c;我们选择不需要的 node_modules 按下空格即可删除。

sentinel2 L2A处理基线04.00 反射率计算方法

sentinel2 处理基线04.00发布后&#xff0c;L2A地表反射率计算方式也发生了调整&#xff1b;根据新版的数据说明&#xff0c;新版数据增加了负值偏移。因此计算时需要读取数据产品中MTD_MSIL2A.xml的元文件。注意&#xff0c;相比之前的版本&#xff0c;元文件中增加了BOA_ADD_…

django创建一个新的应用

使用 python manage.py startapp myapp 命令可以在你的 Django 项目中创建一个新的应用&#xff0c;名为 myapp。应用是 Django 项目的组成部分&#xff0c;可以帮助你组织代码和功能。执行该命令后&#xff0c;会在你的项目目录下创建一个名为 myapp 的文件夹&#xff0c;包含…

docker部署minio文件服务器

1. 拉取镜像 docker search minio docker pull minio/minio2. 创建映射 mkdir -p /root/docker_app/minio_data mkdir -p /root/docker_app/minio_config3. 执行docker run 自定义用户和秘钥安装: admin/admin123456 docker run -p 9000:9000 -p 9001:9001 -d --name mini…

JavaScript 可视化案例详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

大模型驱动的自主智能体全面调研

人工智能咨询培训老师叶梓 转载标明出处 基于LLMs构建的自主智能体&#xff0c;有望实现类似人类的决策能力。图 1 展示了LLMs驱动的自主智能体领域的增长趋势。从2021年1月到2023年8月&#xff0c;不同颜色代表不同类别的智能体。例如&#xff0c;游戏智能体旨在模拟游戏玩家…

MySQL那些事(InnoDB架构和存储结构)

目录 一、序言二、InnoDB架构三、InnoDB内存结构1、Buffer Pool (缓冲池)2、Change Buffer3、Log Buffer 四、InnoDB磁盘结构1、表空间2、Doublewrite Buffer(双写缓冲区)3、Redo Log4、Undo Log 五、结语 一、序言 本节内容为博主根据MySQL 8.0版本官方文档手动翻译过后的最新…

pycharm 配置篇

方法注释 使用方式为&#xff0c;在方法名下方输入三个双&#xff08;单&#xff09;引号&#xff0c;回车&#xff0c;自动生成。五种风格的样式如下&#xff1a; def docstrings_func_plain(parm_a, parm_b, parm_c):"""Plain 风格"""def docs…

笔记本电脑如何改ip地址:操作指南与注意事项

在信息时代的浪潮中&#xff0c;网络已成为我们日常生活与工作中不可或缺的一部分。对于笔记本电脑用户而言&#xff0c;IP地址作为设备在网络中的唯一标识&#xff0c;其重要性不言而喻。无论是出于网络安全、网络测试还是特殊网络环境等需求&#xff0c;了解如何修改笔记本电…

NVIDIA Hopper 架构深入

NVIDIA Hopper 架构 GPU 的重要新功能。 文章目录 一、Transformer engine 变压器发动机二、第四代 NVLink 和 NVLink 网络三、第三代 NVSwitch四、New NVLink Switch System 新的 NVLink 开关系统五、PCIe Gen 5 PCIe 第 5 代一、Transformer engine 变压器发动机 Transforme…

java给word设置复选框

poi设置 使用"Wingdings 2" 字体 WordUtil.appendText(paragraph, "\uF052", "Wingdings 2",null); WordUtil.appendText(paragraph, "□", null);选中的复选框: poi导出pdf的时候正常使用aspose-words导出pdf就空了 使用默认字体…

给自己的项目(vue3)中添加 下雪/樱花飘落的背景

查看更佳效果前往我的博客&#xff0c; 可切换 snows_ls BLOGhttp://124.223.41.220/ 0、效果图 樱花飘落 雪花飘落 1、安装 yarn add jparticles / npm i jparticles 2、引入 import { Snow } from jparticles; // 引入粒子效果库 引入雪花效果库 3、使用 在项目中的app.…

onnx TRT 版本对应关系

Onnx 版本和opset 关系 https://github.com/onnx/onnx/blob/main/docs/Versioning.md Onnx runtime 对应 onnx opset 版本 Compatibility | onnxruntime Tensor RT 和onnx 支持版本可以看如下并选择对应分支 https://github.com/onnx/onnx-tensorrt/blob/release/8.4-GA/doc…

企业内训|AI助力智能办公与职场效能提升-青岛某国资平台

9月25日&#xff0c;TsingtaoAI派驻讲师进驻现场&#xff0c;为青岛市某国资平台公司员工交付“AI助力智能办公与职场效能提升”企业内训&#xff0c;整个培训通过AIGC的实际应用案例&#xff0c;帮助学员掌握智能办公的常用工具&#xff0c;提升工作流程优化和决策效率。课程涵…

衡石分析平台系统管理手册-智能运维之软件授权

软件授权​ 在设置->软件授权页面可以看到授权时间、有效期、用户上限、请求码、租户数上限、租户内用户数上限。 请求码是衡石系统用于生成注册码的一段代码&#xff0c;安装衡石系统后&#xff0c;就会自动生成一个请求码&#xff0c;其中包含了本机的指纹信息和当前 Lic…

BFS 解决 FloodFill 算法

BFS 解决 FloodFill 算法 题目一&#xff1a; 图像渲染1. 题⽬链接&#xff1a;2. 题⽬描述&#xff1a;3. 算法思路&#xff1a;4.代码 题目二&#xff1a; 岛屿数量1. 题⽬链接&#xff1a;2. 题⽬描述&#xff1a;3. 算法思路&#xff1a;4.代码 题目三&#xff1a;被围绕的…

Android Stuido中编译信息出现乱码的解决方式

打开菜单File -> Settings&#xff0c;选择Editor -> File Encodings 窗口&#xff0c;将编码设置为正确的字符集&#xff0c;保证 Global Encoding、Project Encoding 和 Default Encoding for properties files 都设置为 UTF-8。

物联网(二)——MDPI特刊推荐

特刊征稿 01 期刊名称&#xff1a; Application of IoT on Manufacturing, Communication and Engineering 截止时间&#xff1a; 摘要提交截止日期&#xff1a;2025年4月30日 投稿截止日期&#xff1a;2025年6月30日 目标及范围&#xff1a; 感兴趣的主题包括但不限于以…