STL--set和multiset集合

在这里插入图片描述


set和multiset会根据特定的排序准则,自动将元素排序。两者不同之处在于multiset 允许元素重复而 set 不允许。如下图:

在这里插入图片描述
使用set或multiset,必须先包含头文件:

#include <set>

上述两个类型都被定义为命名空间std内的class template:

namespace std {
    template <typename T,
    typename Compare = less<T>,
    typename Allocator = allocator<T> >
    class set;

    template <typename T,
    typename Compare = less<T>,
    typename Allocator = allocator<T> >
    class multiset;
}

其中T是能进行排序的数据类型。第二个参数是进行排序的规则,默认为升序(小于,<),第三个是内存分配器,不用管。

set 和multiset通常用平衡二叉树(balanced binary tree,确切说是红黑树)实现。这样在插入数据时能自动排序,使得查找元素时有良好性能。其查找函数具有对数O(logn)时间复杂度。

但是,自动排序也造成set和multiset的一个重要限制:你**不能直接改变元素值,**因为这样会打乱原本正确的顺序。

在这里插入图片描述
从其接口也能反映这种情况:

set和multiset不提供任何函数可以直接访问元素。

通过迭代器访问元素时都是常量。

1.1 定义及初始化🍗

set的定义和初始化如下:


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

//输出s(升序)的所有数据
void Show(const set<int>& s)
{
    for (auto i : s)
        cout << i << " ";
    cout << endl;
}

//输出s(降序)的所有数据
void Show(const set<int,greater<int>>&s)
{
    for (auto i : s)
        cout << i << " ";
    cout << endl;
}

int main()
{
    set <int> s0;//创建一个空的int set集合    
    s0.insert(5); //插入数据    
    s0.insert(3);    
    s0.insert(1);    
    s0.insert(2);    
    s0.insert(4);    
    s0.insert(4);//相同数据插入失败    

    set <int> s1(s0); //利用原来的set对象,创建一个新的set对象    
    set <int> s2 = s1;//同上    
    set <int> s3(s0.begin(), --s0.end());//利用迭代器创建一个新的set对象




    set <int> s4{  1, 6, 3, 5, 4, 2  };//利用初始化列表创建一个set对象,可以无序    

    cout << "s0:"; Show(s0); //输出数据    
    cout << "s1:"; Show(s1);    
    cout << "s2:"; Show(s2);    
    cout << "s3:"; Show(s3);    
    cout << "s4:"; Show(s4);    

    cout << "降序的集合" << endl;    
    set <int, greater<int> > s5; //创建一个降序的set集合    
    s5.insert(10);//插入数据    
    s5.insert(40);    
    s5.insert(30);    
    s5.insert(20);    
    cout << "s5:"; Show(s5);//输出数据    

    return 0;    
}

multiset定义和初始化如下:


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

//输出s(升序)的所有数据
void Show(const multiset<int>& s)
{
    for (auto i : s)
        cout << i << " ";
    cout << endl;
}

//输出s(降序)的所有数据
void Show(const multiset<int, greater<int>>& s)
{
    for (auto i : s)
        cout << i << " ";
    cout << endl;
}

int main()
{
    multiset <int> s0;//创建一个空的int set集合
    s0.insert(5); //插入数据
    s0.insert(3);
    s0.insert(1);
    s0.insert(2);
    s0.insert(4);
    s0.insert(4);//可以插入相同数据

    multiset <int> s1(s0); //利用原来的set对象,创建一个新的set对象
    multiset <int> s2 = s1;//同上
    multiset <int> s3(s0.begin(), --s0.end());//利用迭代器创建一个新的set对象
    multiset <int> s4{ { 1, 6, 3, 5, 4, 2 } };//利用初始化列表创建一个set对象

    cout << "s0:"; Show(s0); //输出数据
    cout << "s1:"; Show(s1);
    cout << "s2:"; Show(s2);
    cout << "s3:"; Show(s3);
    cout << "s4:"; Show(s4);

    cout << "降序的集合" << endl;
    multiset <int, greater<int> > s5; //创建一个降序的set集合
    s5.insert(10);//插入数据
    s5.insert(40);
    s5.insert(30);
    s5.insert(20);
    cout << "s5:"; Show(s5);//输出数据

    return 0;
}

1.2 向set和multiset中添加元素和删除元素🍗

通过insert函数插入数据。通过erase删除元素。


//输出s(升序)的所有数据
void Show(const set<int>& s)
{
    for (auto i : s)
        cout << i << " ";
    cout << endl;
}
int main()
{
    set<int> s1;
    s1.insert(4);
    s1.insert(1);
    s1.insert(5);
    s1.insert(2);
    cout << "s1:";  Show(s1);

    s1.erase(2);
    cout << "删除2后,s1:";  Show(s1);

    s1.clear();
    cout << "清空后,s1:";  Show(s1);

    return 0;
}

1.3 常用迭代器🍗

set和multiset支持双向迭代器,不支持随机迭代器,可以往前和往后,但不能+1,-1(这是随机迭代器)等。
常用的迭代器如下:
s.begin()
第一个元素的迭代器
s.end()
最后一个元素的下一个位置迭代器(尾后迭代器或尾迭代器)
s.cbegin()
第一个元素的常量迭代器(不修改元素内容)
s.cend()
尾后常量迭代器(不修改元素内容)
s.rbegin()
第一个反向迭代器
s.rend()
尾后反向迭代器

int main()    
{
    set<int> s1;    
    s1.insert(4);    
    s1.insert(1);    
    s1.insert(5);    
    s1.insert(2);    
    cout << "从头到尾输出s1:";    
    for (auto p = s1.begin(); p != s1.end(); p++)    
        cout << *p << " ";    
    cout << endl;    

    cout << "从后往前输出s1:";    
    for (auto p = s1.rbegin(); p != s1.rend(); p++)    
        cout << *p << " ";    
    cout << endl;    

    auto p = s1.begin();    
    cout << "第二个元素:"<< * (++p) << endl;//输出第二个元素    
    cout << "第一个元素:"<< * (--p) << endl;//输出第一个元素    
    //cout << *(p + 1) << endl;//错误    

    return 0;    
}

1.4 set和multiset常用的运算符🍗

set和multiset类既支持常用的=,==,!=,< , >等运算符,也可以通过调用其成员函数来执行相应的操作。下面列举了其常用的操作。详细情况可以参考set或multiset帮助手册。


//输出s(升序)的所有数据    
void Show(const set<int>& s)    
{
    for (auto i : s)    
        cout << i << " ";    
    cout << endl;    
}

int main()    
{
    set<int> s1;    
    s1.insert(4);    
    s1.insert(1);    
    s1.insert(5);    
    s1.insert(2);    
    cout << "s1:";  Show(s1);    

    set<int> s2;    
    s2 = s1;    
    cout << "s2:";  Show(s2);    
    if (s1 == s2)    
        cout << "s1 == s2" << endl;    
    s2.insert(7);    
    cout << "往s2插入7后,";    
    if (s1 > s2)    
        cout << "s1 > s2" ;    
    else if (s1 < s2)    
        cout << "s1 < s2" ;    

    //cout << s1[1] << endl;//错误    

    return 0;    
}

1.5 set和multiset常用成员函数🍗

下面列举set和multiset对象常用的成员函数,详细的介绍请查看帮助手册。

在这里插入图片描述

1.6 set应用场景🍗

set在C++中是一个内部自动有序且不含重复元素的容器,它的应用场景广泛且多样。以下是一些set的常见应用场景:

1.自动排序
如果需要对元素保持持续的排序状态,如维持一个按字母顺序排列的单词列表、存储并维护一个按年龄升序或降序排列的人口数据库等,std::set 可以实现这一功能。每次插入新元素,容器都会自动调整元素的顺序。

当然如果仅仅是排序,可以使用sort函数进行排序.
sort排序是在排序瞬间的,如果又插入新的数据可能不再有序
set的有序是持续的,不管插入还是删除数据它始终有序

2.快速查找
由于set内部采用了高效的平衡查找二叉树(如红黑树),因此它提供快速的查找性能。包括检查元素是否已存在(.count() 或 .find())、查找特定值的下一个/前一个元素(迭代器操作)。这对于实现诸如查找词汇表中的下一个更大词、或者在游戏中查找排名高于当前玩家的下一个玩家等场景很有用。


本篇完!🍗

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

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

相关文章

挖掘抖快销售榜TOP500,这些单品正在引爆夏日市场!

凉鞋、短裤、草席、风扇……一个个夏日“限定”品类在4月就开始冲上抖音、快手两大电商的品类销售榜时&#xff0c;预示着夏日营销在春季已悄悄打响。 在炎炎夏日来临之前&#xff0c;品牌方们都会迎接一次夏日营销“大考”&#xff0c;铆足了劲调动消费者的积极性&#xff0c;…

揭秘Python的魔法:装饰器的超能力大揭秘 ‍♂️✨

文章目录 Python进阶之装饰器详解1. 引言装饰器的概念与意义装饰器在Python编程中的作用 2. 背景介绍2.1 函数作为对象2.2 高阶函数 3. 装饰器基础3.1 理解装饰器3.2 装饰器的工作原理 4. 带参数的装饰器4.1 为什么需要带参数4.2 实现带参数的装饰器使用函数包裹装饰器使用类实…

React开发环境配置详细讲解-04

React环境 前端随着规范化&#xff0c;可以说规范和环境插件配置满天飞&#xff0c;笔者最早接触的是jquery&#xff0c;那个开发非常简单&#xff0c;只要引入jquery就可以了&#xff0c;当时还写了一套UI框架&#xff0c;至今在做小型项目中还在使用&#xff0c;show一张效果…

小恐龙跳一跳源码

小恐龙跳一跳源码是前两年就火爆过一次的小游戏源码&#xff0c;不知怎么了今年有火爆了&#xff0c;所以今天就吧这个源码分享出来了&#xff01;有喜欢的直接下载就行&#xff0c;可以本地单机直接点击index.html进行运行&#xff0c;又或者放在虚拟机或者服务器上与朋友进行…

FL Studio2025中文最新版本专业编曲软件有哪些新功能?

FL Studio 21&#xff0c;也被音乐制作爱好者亲切地称为“水果编曲软件”&#xff0c;是比利时的Image-Line公司研发的一款完整的音乐制作环境或数字音频工作站&#xff08;DAW&#xff09;。自从1990年代推出以来&#xff0c;FL Studio 以其直观的用户界面、丰富的插件支持和强…

PHP质量工具系列之php_CodeSniffer

PHP_CodeSniffer 是一组两个 PHP 脚本&#xff1a;主脚本 phpcs 对 PHP、JavaScript 和 CSS 文件进行标记&#xff0c;以检测是否违反定义的编码标准&#xff1b;第二个脚本 phpcbf 自动纠正违反编码标准的行为。PHP_CodeSniffer 是一个重要的开发工具&#xff0c;可以确保你的…

【电路笔记】-有源高通滤波器

有源高通滤波器 文章目录 有源高通滤波器1、概述2、有源高通滤波器3、有源高通滤波器示例4、二阶高通有源滤波器有源高通滤波器可以通过将无源 RC 滤波器网络与运算放大器相结合来创建,以产生具有放大功能的高通滤波器。 1、概述 有源高通滤波器 (HPF) 的基本操作与其等效 RC…

【Crypto】摩丝

文章目录 一、摩斯解题感悟 一、摩斯 很明显莫尔斯密码 iloveyou还挺浪漫 小小flag&#xff0c;拿下 解题感悟 莫尔斯密码这种题还是比较明显的

游戏安全防控有招了! MMO游戏安全场景解决方案

2024年4月10日&#xff0c;暴雪娱乐与网易共同宣布&#xff1a;停服442天后&#xff0c;那款曾经让数百万国内玩家为之痴迷的MMO游戏《魔兽世界》国服要重新回归了。 还记得服务器关闭倒计时15分钟开始的时候&#xff0c;素不相识的大家就在频道中互相告别&#xff0c;“愿风指…

spring boot集成Knife4j

文章目录 一、Knife4j是什么&#xff1f;二、使用步骤1.引入依赖2.新增相关的配置类3.添加配置信息4.新建测试类5. 启动项目 三、其他版本集成时常见异常1. Failed to start bean ‘documentationPluginsBootstrapper2.访问地址后报404 一、Knife4j是什么&#xff1f; 前言&…

微服务项目收获和总结---第4天(文章审核和保存)

文章审核以及APP端保存文章 业务流程&#xff1a; App端保存接口&#xff1a; 数据库表详情 文章的基本信息表&#xff1a;id&#xff0c;标题&#xff0c;作者id&#xff0c;频道id...... 文章的权限/配置表&#xff1a;存储文章是否可以评论&#xff0c;是否上架&#xff…

在docker中运行SLAM十四讲程序

《十四讲》的示例程序依赖比较多&#xff0c;而且系统有点旧。可以在容器中运行。 拉取镜像 docker pull ddhogan/slambook:v0.1这个docker对应的github&#xff1a;HomeLH/slambook2-docker 拉下来之后&#xff0c;假如是Windows系统&#xff0c;需要使用XLaunch用于提供X11…

番外篇 | YOLOv5-SPD:用最简单的方式完成低分辨率图像和小目标检测升级

前言:Hello大家好,我是小哥谈。论文提出了一个新的CNN构建模块称为SPD-Conv,用来替换每个步长卷转层和每个池化层(从而完全消除它们)。SPD-Conv由一个空间到深度(SPD)层和一个非步长卷积(Conv)层组成。本文详细介绍了如何在YOLOv5中引入SPD-Conv,助力助力低分辨率与小…

掌握代码注释:提升代码可读性的秘密武器

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、为什么我们需要注释&#xff1f; 二、如何添加单行注释&#xff1f; 使用井号 # 添加单…

C++贪心算法(4)

过河的最短时间 #include<bits/stdc.h> using namespace std; int main() {int a[1010]{0};int n;cin>>n;for(int i0;i<n;i){cin>>a[i];}sort(a0,an);int xn-2;int yn-1;int tmpa[1];while(true){int tmp1a[0]a[y]a[1]a[1];int tmp2a[0]a[y]a[0]a[x];if(t…

Golang | Leetcode Golang题解之第110题平衡二叉树

题目&#xff1a; 题解&#xff1a; func isBalanced(root *TreeNode) bool {return height(root) > 0 }func height(root *TreeNode) int {if root nil {return 0}leftHeight : height(root.Left)rightHeight : height(root.Right)if leftHeight -1 || rightHeight -1 …

2024年收集搜索引擎蜘蛛大全以及浏览器模拟蜘蛛方法

对于做SEOer来说经常和搜索引擎蜘蛛打交道&#xff0c;下面整理收集了最全的搜索引擎蜘蛛大全。供有需要的朋友使用&#xff0c;建议收藏。 搜索引擎蜘蛛大全 "TencentTraveler", "Baiduspider", "BaiduGame", "bingbot",//必应蜘蛛…

MaxEnt模型文章中存在的问题和处理方法(050B更新)2024.5.24

目前多数MaxEnt文章中存在的问题和处理方案。 **问题一&#xff1a;**变量数据使用问题&#xff0c;很多文章把所有变量数据直接使用&#xff0c;但是温度和土壤、植被类型等属于不同数据类型&#xff0c;在数据使用时参数配置是不一样的&#xff0c;产生的结果文件也是不一样的…

Generative Action Description Prompts for Skeleton-based Action Recognition

标题&#xff1a;基于骨架的动作识别的生成动作描述提示 源文链接&#xff1a;https://openaccess.thecvf.com/content/ICCV2023/papers/Xiang_Generative_Action_Description_Prompts_for_Skeleton-based_Action_Recognition_ICCV_2023_paper.pdfhttps://openaccess.thecvf.c…

【openlayers系统学习】1.5交互-捕捉要素

五、捕捉要素 Snapping 捕捉 您可能已经注意到&#xff0c;很容易绘制与现有要素不完全对齐的要素。此外&#xff0c;在修改要素时&#xff0c;我们可能会破坏拓扑关系&#xff0c;导致原本相邻的多边形之间出现空隙。Snap 交互操作可以帮助在绘制和编辑要素时保持拓扑关系。…