stl_set

文章目录

  • set
    • 1.关联式容器
    • 2.键值对
    • 3. set
      • 3.1 set介绍
      • 3.2 set的使用
        • 3.2.1 pair
        • 3.2.2 find
        • 3.2.3 lower_bound
      • 3.3 multiset
        • 3.3.1 multiset的介绍
        • 3.3.2 multiset的使用
        • 3.3.3 find
        • 3.3.4 equal_range
        • 3.3.5 erase

set

1.关联式容器

在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这些容器统称为 序列式容器 ,因为其底层为线性序列的数据结构,里面存储的是元素本身。

那什么是关联式容器?它与序列式容器有什么区别?

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是 <key, value> 结构的键值对,在数据检索时比序列式容器效率更高。

2.键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义

3. set

3.1 set介绍

set文档介绍

翻译:

  1. set是按照一定次序存储元素的容器

  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。

  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。

  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。

  5. set在底层是用二叉搜索树(红黑树)实现的。

注意:

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  2. set中插入元素时,只需要插入value即可,不需要构造键值对。
  3. set中的元素不可以重复(因此可以使用set进行去重)。
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列
  5. set中的元素默认按照小于来比较
  6. set中查找某个元素,时间复杂度为: l o g 2 n log_2 n log2n
  7. set中的元素不允许修改(为什么?)
  8. set中的底层使用二叉搜索树(红黑树)来实现

3.2 set的使用

  1. set的模板参数列表

在这里插入图片描述

T: set中存放元素的类型,实际在底层存储<value, value>的键值对。

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

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

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);
    s.insert(3);
    s.insert(3);
    s.insert(3);
    s.insert(5);
    s.insert(6);

    set<int>::iterator it = s.begin();
    while(it != s.end())
    {
        cout << *it << " ";
        ++it;
    }
}

int main()
{
    test_set();
    return 0;
}

验证结果:

在这里插入图片描述

当然,遍历set值,也可以使用范围for:

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);
    s.insert(3);
    s.insert(3);
    s.insert(3);
    s.insert(5);
    s.insert(6);

    set<int>::iterator it = s.begin();
    while(it != s.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;

    for(auto e : s)
    {
        cout << e << " ";
    }
}

int main()
{
    test_set();
    return 0;
}

运行结果对比:

在这里插入图片描述

正所谓只要支持迭代器,就一定支持范围for!!

可以发现,有相同的值只返回了一次,而且走的是中序遍历。

注:set的底层是红黑树,本质也是一个二叉搜索树,当有相同的值时便不会再插入了,返回的是false

这是就一个问题了,查找到相同值时,布尔值是如何返回接受的呢?

答:通过pair接受返回值

3.2.1 pair

这里来查看pair接口:

在这里插入图片描述

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)
    {}
};

下面用pair接受返回值示例:

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);
    s.insert(3);
    s.insert(3);
    s.insert(3);
    s.insert(5);
    s.insert(6);
    auto ret1 = s.insert(5);
    cout << ret1.second << endl;

    pair<set<int>::iterator, bool> ret2 = s.insert(5);
    cout << ret2.second << endl;

    pair<set<int>::iterator, bool> ret3 = s.insert(4);
    cout << ret3.second << endl;
}

int main()
{
    test_set();
    return 0;
}

接收结果:

在这里插入图片描述

从结果可以看出,插入成功返回 1 ,插入失败返回 0 。

3.2.2 find

find接口简介:

在这里插入图片描述

返回值介绍:

在这里插入图片描述

find返回的就是迭代器 !!

当想在set中删除值时,也可以通过find来删除:

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);

    s.erase(1);  //直接删除

    set<int>::iterator it = s.find(2);  //find函数删除
    if (it != s.end())
    {
        s.erase(it);
    }

    for (auto e : s)
    {
        cout << e << " ";
    }
}

int main()
{
    test_set();
    return 0;
}

删除结果:

在这里插入图片描述

如果查找的不存在,则程序会崩溃掉!!

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);

    set<int>::iterator it = s.find(30);
    s.erase(it);

    for (auto e : s)
    {
        cout << e << " ";
    }
}

int main()
{
    test_set();
    return 0;
}

结果:

在这里插入图片描述

这里用的是vscode为显示任何效果,如果用vs,则会显示程序崩溃窗口!!

当夜也有解决方法:

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);

    set<int>::iterator it = s.find(30);
    if (it != s.end())
    {
        s.erase(it);
    }

    for (auto e : s)
    {
        cout << e << " ";
    }
}

int main()
{
    test_set();
    return 0;
}

在这里插入图片描述

3.2.3 lower_bound

给一个值返回一个迭代器!!

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> myset;
    set<int>::iterator itlow, itup;
    for (int i = 1; i < 10; i++)
    {
        myset.insert(i * 10);   //10 20 30 40 50 60 70 80 90
    }
    itlow = myset.lower_bound(25);  //>= val值的位置的iterator
    itup = myset.upper_bound(60);   //> val值的位置的iterator
    myset.erase(itlow, itup);  //取值范围[25,60]

    for(auto e : myset)
    {
        cout << e << " ";
    }
    cout << endl;
}

int main()
{
    test_set();
    return 0;
}

返回结果:

在这里插入图片描述

注意: set不支持修改!!!其余的功能就是迭代器的正常调用!!

3.3 multiset

3.3.1 multiset的介绍

multiset文档介绍

在这里插入图片描述

[翻译]:

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。

  2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。

  3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。

  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。

  5. multiset底层结构为二叉搜索树(红黑树)。

注意:

  1. multiset中再底层中存储的是<value, value>的键值对

  2. mtltiset的插入接口中只需要插入即可

  3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的

  4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列

3.3.2 multiset的使用

此处只简单演示set与multiset的不同,其他接口接口与set相同:

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    set<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);

    multiset<int>::iterator it = s.begin();
    while(it != s.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}

int main()
{
    test_set();
    return 0;
}

运行结果:

在这里插入图片描述

从结果看来,multiset的功能:排序 + 去重 !!!

3.3.3 find
#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    multiset<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);
    s.insert(2);
    s.insert(5);
    s.insert(2);
    s.insert(5);

    multiset<int>::iterator it = s.begin();
    while(it != s.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;

    //如果有多个值,find返回中序第一个val
    it = s.find(2);
    while(it != s.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}

int main()
{
    test_set();
    return 0;
}

调用结果:

在这里插入图片描述

3.3.4 equal_range

实例:

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    multiset<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);
    s.insert(2);
    s.insert(5);
    s.insert(2);
    s.insert(5);

    cout << "原序列: ";
    for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;

    cout << "现序列: ";
    auto ret = s.equal_range(2);
    s.erase(ret.first, ret.second);
    for(auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;
}

int main()
{
    test_set();
    return 0;
}

调用结果:

在这里插入图片描述

其中,first 和 second 的意义就是:

  • first:>=val值
  • second:>val值

由此可见,其功能就是删除所指定查找的所有重复的val值。

3.3.5 erase

在multiset中的使用:

#include <iostream>
using namespace std;
#include <set>

void test_set()
{
    multiset<int> s;
    s.insert(5);
    s.insert(2);
    s.insert(6);
    s.insert(3);
    s.insert(1);
    s.insert(2);
    s.insert(5);
    s.insert(2);
    s.insert(5);

    cout << "原序列: ";
    for (auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;

    cout << "删除个数: ";
    size_t n = s.erase(2);
    cout << n << endl;
    cout << "现序列: ";
    for(auto e : s)
    {
        cout << e << " ";
    }
    cout << endl;
}

int main()
{
    test_set();
    return 0;
}

删除结果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Zynq 7000 系列中的JTAG和DAP子系统

Zynq 7000系列SoC器件通过标准JTAG调试接口提供调试访问。在内部&#xff0c;SoC设备器件在处理系统&#xff08;PS&#xff09;内部实现了一个Arm调试访问端口&#xff08;DAP&#xff09;&#xff0c;同时在可编程逻辑&#xff08;PL&#xff09;内部实现了一个标准的JTAG测试…

中国人为什么不说自信,而说信天

中国人从来不说自信&#xff0c;中国人信天&#xff0c;老天爷是最公平的。做好自己&#xff0c;天命注定&#xff0c;我都这么努力了&#xff0c;老天爷不帮我帮谁&#xff1f; 中国人信天是有逻辑关系的&#xff0c;很简单&#xff1a;做错事情了或者结果不好了&#xff0c;…

LeetCode - 283.移动零

题目链接&#xff1a; LeetCode - 283.移动零 题目分析&#xff1a; ​​​​​ 题解代码&#xff1a; #include<iostream> #include<vector> using namespace std;class Solution { public:void moveZeroes(vector<int>& nums) {for (int cur 0, des…

Kafka入门介绍+集群部署+简单使用

Kafka入门介绍集群部署简单使用 简介核心概念Broker&#xff08;服务节点/实例&#xff09;Producer&#xff08;生产者&#xff09;Topic&#xff08;主题&#xff09;Partition&#xff08;分区&#xff09;Consumer&#xff08;消费者&#xff09;和Consumer Group&#xff…

volatility内存取证

记录一道volatility内存取证的题目&#xff0c;第一次遇到&#xff0c;现场把环境搞出来&#xff0c;现记录一些操作指令。 一、安装volatility3 1、新建一个kali虚拟机 新建的过程不再赘述。 2、下载volatility3 GitHub - volatilityfoundation/volatility3: Volatility …

21.组件组成

组件组成 组件最大的优势就是可复用性 当使用构建步骤时&#xff0c;我们一般会将 Vue 组件定义在一个单独的 .vue 文件中&#xff0c;这被叫做单文件组件(简称 SFC) 组件组成结构 <template><div>承载标签</div> </template> <script> expor…

政安晨:【Keras机器学习示例演绎】(六)—— 通过 CT 扫描进行 3D 图像分类

目录 简介 设置 下载 MosMedData&#xff1a;胸部CT扫描与COVID-19相关发现 加载数据和预处理 建立训练和验证数据集 数据增强 定义 3D 卷积神经网络 训练模型 模型性能可视化 通过一次 CT 扫描进行预测 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍…

图像处理的魔法师:Pillow 库探秘

文章目录 图像处理的魔法师&#xff1a;Pillow 库探秘第一部分&#xff1a;背景介绍第二部分&#xff1a;库是什么&#xff1f;第三部分&#xff1a;如何安装这个库&#xff1f;第四部分&#xff1a;库函数使用方法第五部分&#xff1a;场景应用第六部分&#xff1a;常见Bug及解…

黑马---苍穹外卖总结上

1.功能模块 1.1 管理端功能 员工登录/退出 , 员工信息管理 , 分类管理 , 菜品管理 , 套餐管理 , 菜品口味管理 , 订单管理 &#xff0c;数据统计&#xff0c;来单提醒。 模块描述登录/退出内部员工必须登录后,才可以访问系统管理后台员工管理管理员可以在系统后台对员工信息进…

layui框架实战案例(27):弹出二次验证

HTML容器 <button class"layui-btn layui-btn-sm layui-btn-danger" lay-event"delete"><i class"layui-icon layui-icon-delete"></i>批量删除</button>删除封装函数 function delAll(school_id, school_name) {var lo…

Java 笔记 03:Java 基础知识,使用 IDEA 创建 Java 项目、设置注释颜色,以及自动生成 JavaDoc

一、前言 记录时间 [2024-04-21] 系列文章简摘&#xff1a; Java 笔记 01&#xff1a;Java 概述&#xff0c;MarkDown 常用语法整理 Java 笔记 02&#xff1a;Java 开发环境的搭建&#xff0c;IDEA / Notepad / JDK 安装及环境配置&#xff0c;编写第一个 Java 程序 本文讲述了…

图论学习总结

目录 图论学习总结前言一、基础知识图的存储图的遍历 二、最短路多源最短路 F l o y d Floyd Floyd​ 算法例题及变形 e g 1 &#xff1a; S o r t i n g I t A l l O u t eg1&#xff1a;Sorting\ It\ All\ Out eg1&#xff1a;Sorting It All Out ( 蓝书例题&#xff0c;传递…

生成人工智能体:人类行为的交互式模拟论文与源码架构解析(2)——架构分析 - 核心思想环境搭建技术选型

4.架构分析 4.1.核心思想 超越一阶提示&#xff0c;通过增加静态知识库和信息检索方案或简单的总结方案来扩展语言模型。 将这些想法扩展到构建一个代理架构&#xff0c;该架构处理检索&#xff0c;其中过去的经验在每个时步动态更新&#xff0c;并混合与npc当前上下文和计划…

计算机视觉——OpenCV Python位运算与图像掩码

概述 位运算与图像掩码的结合允许对图像的特定区域进行精确的操作。通过使用位运算&#xff08;如AND、OR、XOR和NOT&#xff09;&#xff0c;可以基于掩码的选择性地修改图像数据。位运算与图像掩码结合使用的一些关键点和应用场景&#xff1a; 选择性修改&#xff1a; 通过位…

李宏毅2022机器学习/深度学习 个人笔记(1)

本系列用于推导、记录该系列视频中本人不熟悉、或认为有价值的知识点 本篇记录第一讲&#xff08;选修&#xff09;&#xff1a;神奇宝贝分类 如图&#xff0c;为了估算某个样本属于某类的概率&#xff0c;在二分类问题中&#xff0c;我们需要计算红框所示的4个参数&#xff0…

语义分割知识点:UNet、FCN、SegNet、PSPNet、DeepLab系列

语义分割知识点&#xff1a;UNet、FCN、SegNet、PSPNet、DeepLab系列 前言语义分割网络剖析UNet系列UNetUNet网络有几个主要的特点&#xff1a;从UNet结构图可以知道&#xff0c;收敛路径主要的过程为简要总结&#xff1a; UNet为什么UNet可以被剪枝?如何剪枝? 根据子网络在验…

如何打开局域网共享?

局域网共享是一种方便实现文件共享、打印共享和资源访问的技术。通过局域网共享&#xff0c;不同设备之间可以方便地共享文件和资源&#xff0c;提高工作效率和便利性。在网络环境中&#xff0c;使用天联组网工具可以更加快速地实现局域网共享&#xff0c;解决不同地区间的远程…

lesson03:类和对象(中)

1.类的6个默认的成员函数 2.构造函数 3.析构函数 4.拷贝构造函数 1.类的6个默认的成员函数 空类&#xff08;类中一个成员都没没有&#xff09;会有成员函数吗&#xff1f; 其实是有的&#xff01;如果我们在类中什么都不写&#xff0c;编译器会自动生成6个默认成员函数&a…

33. BI - Graph Embedding 回顾以及 GCN 算法介绍

本文为 「茶桁的 AI 秘籍 - BI 篇 第 33 篇」 文章目录 回顾 Graph Embedding什么是 GCNGCN 算法 Hi&#xff0c;你好。我是茶桁。 咱们终于进入核心 BI 课程的最后一部分内容了&#xff0c;之前咱们的重心一直都是在特征选取上&#xff0c;如何获得更好的特征是重中之重&…

踏上R语言之旅:解锁数据世界的神秘密码(二)

R语言学习 文章目录 R语言学习1.数据的R语言表示2.多元数据的R语言调用3.多元数据的简单R语言分析 总结 1.数据的R语言表示 数据框&#xff08;data frame) R语言中用函数data.frame()生成数据框&#xff0c;其句法是&#xff1a; data.frame(data1,data2,…)&#xff0c;例如…