STL--set和multiset集合

news2025/1/16 0:51:31

在这里插入图片描述


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())、查找特定值的下一个/前一个元素(迭代器操作)。这对于实现诸如查找词汇表中的下一个更大词、或者在游戏中查找排名高于当前玩家的下一个玩家等场景很有用。


本篇完!🍗

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

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

相关文章

Platformer Project

Platformer项目适合那些寻找坚实基础来构建你梦想中的3D平台游戏的人,提供受该类型最具影响力游戏启发的核心机制。 一般功能 移动支持; 自定义运动学角色控制器; Humanoid Rig支持(共享动画); 保存/加载(二进制、JSON或Playerprefs); 支持多个存储槽; 三星、硬币和最…

React-JSX基础

什么是JSX 概念&#xff1a;JSX是JavaScript和XML&#xff08;HTML&#xff09;的缩写&#xff0c;表示在JS代码中编写HTML模板结构&#xff0c;它是React中编写UI模板的方式 优势&#xff1a;1.HTML的声明式模板写法 2.JS的可编程能力 JSX的本质 JSX并不是标准的JS语法&…

高集成IP摄像SOC处理方案简介以及芯片介绍SSC336D

时至今日&#xff0c;随着科技越来越快的发展&#xff0c;视频监控领域目前已经向新型 IP 网络进行技术过渡。而 IP 网络摄像系统的初始定义为&#xff1a;网络与视频处理技术相统一的摄像单元。 网络摄像系统拥有自己的 IP 地址和计算功能&#xff0c;能处理网络通信任务。其…

Qt下使用QImage和OpenCV实现图像的拼接与融合

文章目录 前言一、使用QImage进行水平拼接二、使用OpenCV进行水平拼接三、使用OpenCV进行图像融合四、示例完整代码总结 前言 本文主要讲述了在Qt下使用QImage和OpenCV实现图像的拼接与融合&#xff0c;并结合相应的示例进行讲解&#xff0c;以便大家学习&#xff0c;如有错误…

Linux基础(二):环境搭建

本文准备从0开始&#xff0c;一步步搭建一套属于自己的Linux系统环境&#xff0c;这将是后续学Linux、用Linux、Linux环境编程、应用和项目部署、工具实验等一系列学习和实践的基石&#xff0c;希望对小伙伴们有帮助。提前备好Linux编程实验环境非常重要&#xff0c;建议人手一…

【小笔记】如何在docker中更新或导入neo4j数据?

如何在docker中更新或导入neo4j数据&#xff1f; &#xff08;1&#xff09;背景&#xff1a; 我尝试了4.4.9和5.19.0版本的Neo4j社区版&#xff0c;基于他们的镜像创建容器后&#xff0c;需要导入我准备好的csv文件或dump文件&#xff0c;因为数据量非常大&#xff0c;所以采…

IntelliJ IDEA集成Baidu Comate,商城系统支付交易功能开发实战

文章目录 Baidu Comate介绍安装配置体验安装插件配置体验注释生成代码技术问答 实战设计表生成代码导入数据 总结 Baidu Comate介绍 在科技互联网飞速发展的今天&#xff0c;百度凭借其深厚的技术积累和创新能力&#xff0c;推出了一款名为Baidu Comate智能代码助手的产品。该…

JS-03深入了解构造函数

目录 1 引入构造函数 2 通过构造函数创建对象-内置 3 自定义一个构造函数来创建对象 3.1 构造函数的概念 3.2关于new Object() 3.3 构造函数的执行过程 3.3.1构造函数的返回值 3.3.2 如何判断一个数据是否是复杂数据类型&#xff1f; 3.3.3为什么要理解构造函数的返回值&…

15、24年--信息系统管理——管理要点

1、数据管理 数据管理使指通过规划、控制与提供数据和信息资产的职能,包括开发、执行和监督有关数据的计划、策略、方案、项目、流程、方法和程序,以获取、控制、保护、交付和提高数据和信息资产价值。 DCMM定义了数据战略、数据治理、数据架构、数据应用、数据安全、…

如何官方查询论文分区,中科院及JCR

中科院分区 有一个小程序&#xff1a;中科院文献情报中心分区表 点2023升级版&#xff0c;输入期刊名 大类1区 JCR分区 进入官方网站 Journal Citation Reports 输入要查询的期刊名&#xff0c;点开 拼命往下拉 这就是根据影响因子的排名&#xff0c;在computer science&am…

柱状图中最大的矩形 - LeetCode 热题 73

大家好&#xff01;我是曾续缘&#x1f61b; 今天是《LeetCode 热题 100》系列 发车第 73 天 栈第 5 题 ❤️点赞 &#x1f44d; 收藏 ⭐再看&#xff0c;养成习惯 柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xf…

使用docker-compose部署时序数据库InfluxDB1.8.4

背景 如今 InfluxDB 已经更新到了 2.x &#xff0c; InfluxDB 1.x 和 2.x 版本之间有几个主要的区别&#xff1a; 数据模型&#xff1a; 1.x&#xff1a;使用数据库和保留策略来组织数据。 2.x&#xff1a;引入了组织&#xff08;organizations&#xff09;和存储桶&#xff…

抖音极速版:抖音轻量精简版本,新人享大福利

和快手一样&#xff0c;抖音也有自己的极速版&#xff0c;可视作抖音的轻量精简版&#xff0c;更专注于刷视频看广告赚钱&#xff0c;收益比抖音要高&#xff0c;可玩性更佳。 抖音极速版简介 抖音极速版是一个提供短视频创业和收益任务的平台&#xff0c;用户可以通过观看广…

【LeetCode】【1】两数之和(1141字)

文章目录 [toc]题目描述样例输入输出与解释样例1样例2样例3 提示进阶Python实现哈希表 个人主页&#xff1a;丷从心 系列专栏&#xff1a;LeetCode 刷题指南&#xff1a;LeetCode刷题指南 题目描述 给定一个整数数组nums和一个整数目标值target&#xff0c;请在该数组中找出…

【linux-kernel内核移植记录-踩坑以及注意事项】

目录 1. 环境介绍2.编译原厂的kernel2.1 通过tftp挂载原厂linux内核 3. 修改对应的驱动3.1 修改CPU频率3.2 修改MMC3.3 修改网络驱动 4. 总结 1. 环境介绍 ubuntu版本16.04I.MX6ULL开发板&#xff0c;阿尔法uboot正常启动&#xff0c;能ping通ubuntu&#xff0c;可通过tftpboo…

使用delphi11编写一个基于xls作为数据库的照片展示程序

1、创建xls文档可以参考前一篇博客&#xff0c;并使用wps将文档保存为2003格式xls后缀。 2、在form上面放置adoconnection、adotable、datasource、spinedit、timer、checkbox、image、4个button组件。 image的设置&#xff1a; Image1.Align : alClient; Image1.Center : Tr…

【全开源】答题考试系统源码(FastAdmin+ThinkPHP+Uniapp)

答题考试系统源码&#xff1a;构建高效、安全的在线考试平台 引言 在当今数字化时代&#xff0c;在线考试系统已成为教育机构和企业选拔人才的重要工具。一个稳定、高效、安全的答题考试系统源码是构建这样平台的核心。本文将深入探讨答题考试系统源码的关键要素&#xff0c;…

mysql binlog统一恢复误删数据库、表、数据(没有任何备份)

先将mysql文件夹中的my.ini进行设置 在 [mysqld]下边加上 # mysql-bin 是日志的基本名或前缀名&#xff0c;最后生成的日志文件是mysql-bin.000001类似&#xff0c;重启mysql数字会递增 log_binmysql-bin #binlog格式&#xff0c;statement&#xff0c;row&#xff0c;mixed可…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第28课-avatar玩家3D形象

【WEB前端2024】开源智体世界&#xff1a;乔布斯3D纪念馆-第28课-avatar玩家3D形象 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界…