【STL十】关联容器——set容器、multiset容器

news2025/9/14 23:21:14

【STL十】关联容器——set容器、multiset容器

  • 一、set简介
  • 二、头文件
  • 三、模板类
    • 四、set的内部结构
  • 五、成员函数
    • 1、迭代器
    • 2、元素访问
    • 3、容量
    • 4、修改操作
    • ~~5、操作~~
    • 5、查找
    • 6、查看操作
  • 六、demo
    • 1、查找find
    • 2、修改操作insert
    • 3、修改操作erase、clear
  • 七、multiset

set和multiset会根据特定的排序准则,自动将元素排序。两者不同之处在于multiset允许元素重复而set不允许。(如下图)
在这里插入图片描述

一、set简介

  • 和 map、multimap 容器不同,使用 set 容器存储的各个键值对,要求键 key 和值 value 必须相等。
  • map、multimap 容器都会自行根据键的大小对存储的键值对进行排序,set 容器也会如此,只不过 set 容器中各键值对的键 key 和值 value 是相等的,根据 key 排序,也就等价为根据 value 排序。
  • 使用 set 容器存储的各个元素的值必须各不相同。更重要的是,从语法上讲 set 容器并没有强制对存储元素的类型做 const 修饰,即 set 容器中存储的元素的值是可以修改的。但是,C++ 标准为了防止用户修改容器中元素的值,对所有可能会实现此操作的行为做了限制,使得在正常情况下,用户是无法做到修改 set 容器中元素的值的。

对于初学者来说,切勿尝试直接修改 set 容器中已存储元素的值,这很有可能破坏 set 容器中元素的有序性,最正确的修改 set 容器中元素值的做法是:先删除该元素,然后再添加一个修改后的元素。

二、头文件

#include<set>

三、模板类

template < class T,                        // 键 key 和值 value 的类型
           class Compare = less<T>,        // 指定 set 容器内部的排序规则
           class Alloc = allocator<T>      // 指定分配器对象的类型
           > class set;

四、set的内部结构

  • set/multiset通常以平衡二叉树完成(balanced binary tree);(如下图)

  • 自动排序的主要优点在于令二叉树于查找元素时拥有良好效能。其查找函数具有对数复杂度。在拥有 1000 个元素的 set 或 multiset 中查找元素,二叉树查找动作(由成员函数执行)的平均时间为线性查找(由STL 算法执行)的 1/50。

  • 但是,自动排序造成 set 和 multiset 的一个重要限制:你不能直接改变元素值,因为这样会打乱原本正确的顺序。
    因此,要改变元素值,必须先删除旧元素,再插入新元素。以下接口反映了这种行为:

    • Set 和 multiset 不提供任何操作函数可以直接访问元素。
    • 通过迭代器进行元素间接访问,有一个限制:从迭代器的角度看,元素值是常量。

在这里插入图片描述

五、成员函数

1、迭代器

成员函数功能
begin()同array容器
end()同array容器
rbegin()同array容器
rend()同array容器
cbegin()同array容器
cend()同array容器
crbegin()同array容器
crend()同array容器

2、元素访问

成员函数功能
operator[]同array容器
at(n)同array容器
front()同array容器
back()同array容器
data()同array容器

3、容量

成员函数功能
size()同array容器
max_size()同array容器
empty()同array容器
reserve同vector容器
capacity同vector容器
shrink_to_fit同vector容器

4、修改操作

成员函数功能
clear()同vector容器
insert()同vector容器
insert_or_assign(C++17)插入元素,或若键已存在则赋值给当前元素
emplace()同vector容器
emplace_hint()在本质上和 emplace() 在 map 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。
try_emplace(C++17)若键不存在则原位插入,若键存在则不做任何事
erase()同vector容器
push_back()同vector容器
emplace_back()同vector容器
pop_back()同vector容器
push_front()同vector容器
emplace_front()同vector容器
pop_front()同vector容器
resize()同vector容器
swap()同vector容器
extract(C++17)从另一容器释出结点
merge(C++17)从另一容器接合结点

5、操作

成员函数功能
merge()list容器
splice()list容器
remove(val)list容器
remove_if()list容器
reverse()list容器
unique()list容器
sort()list容器

5、查找

成员函数功能
count(key)同map容器
find(key)同map容器
contains (C++20)同map容器
equal_range(key)同map容器
lower_bound(key)同map容器
upper_bound(key)同map容器

6、查看操作

成员函数功能
key_comp同map容器
value_comp同map容器

六、demo

1、查找find

  • 返回值
    指向键等于 key 的元素的迭代器。若找不到这种元素,则返回尾后(见 end() )迭代器。
#include <iostream>
#include <string>       // string
#include<set>
using namespace std;
int main() {
    set <string> myset{
        "小b",
        "小c",
        "小a",
        "小d",
    };

    auto ite = myset.find("小d");
    cout << "find = " << *ite << endl;
    
    for (auto iter = myset.begin(); iter != myset.end(); ++iter) {
        cout << *iter << endl;
    }

    return 0;
}

输出

find = 小d
小a
小b
小c
小d

2、修改操作insert

返回值

  • lower_bound:指向首个不小于 key 的元素的迭代器。若找不到这种元素,则返回尾后迭代器
  • upper_bound:指向首个大于 key 的元素的迭代器。若找不到这种元素,则返回尾后迭代器

正常场景

#include <iostream>
#include <string>       // string
#include<set>
using namespace std;
int main() {
    set <string> myset{
        "小b",
        "小c",
        "小a",
        "小d",
    };

    auto ite = myset.insert("小e");
    cout << *(ite.first) << " " << ite.second << endl;
    
    set<string> set2;
    set2.insert(myset.begin(), myset.end());

    for (auto iter = set2.begin(); iter != set2.end(); ++iter) {
        cout << *iter << endl;
    }

    return 0;
}

输出

小e 1
小a
小b
小c
小d
小e

3、修改操作erase、clear

  • erase

set 类模板中,erase() 方法有 3 种语法格式,分别如下:

//删除 set 容器中值为 val 的元素
size_type erase (const value_type& val);
//删除 position 迭代器指向的元素
iterator  erase (const_iterator position);
//删除 [first,last) 区间内的所有元素
iterator  erase (const_iterator first, const_iterator last);

demo

#include <iostream>
#include<set>
using namespace std;
int main() {
    set <int> myset{ 1,2,3,4,5 };

    int num = myset.erase(2);
    cout << "num = " << num << endl;
    cout << "myset.size = " << myset.size() << endl << endl;
    
    set<int>::iterator ite = myset.erase(myset.begin());
    cout << "ite = " << *ite << endl;
    cout << "myset.size = " << myset.size() << endl << endl;


    set<int>::iterator ite2 = myset.erase(myset.begin(),--myset.end());
    cout << "ite = " << *ite2 << endl;
    cout << "myset.size = " << myset.size() << endl;

    return 0;
}

输出

num = 1
myset.size = 4


ite = 3
myset.size = 3


ite = 5
myset.size = 1

  • clear
    语法格式如下:
void clear();

显然,该方法不需要传入任何参数,也没有任何返回值。

#include <iostream>
#include<set>
using namespace std;
int main() {
    set <int> myset{ 1,2,3,4,5 };
    cout << "myset.size = " << myset.size() << endl;
 
    myset.clear();

    cout << "myset.size = " << myset.size() << endl;

    return 0;
}

输出

myset.size = 5
myset.size = 0

七、multiset

和set 容器不同的是,multiset 容器可以存储多个值相同的元素。

  • 模板类
template < class T,                        // 存储元素的类型
           class Compare = less<T>,        // 指定容器内部的排序规则
           class Alloc = allocator<T> >    // 指定分配器对象的类型
           > class multiset;
  • demo
#include <iostream>
#include <set>
using namespace std;
int main() {
    std::multiset<int> mymultiset{ 1,2,2,2,3,4,5 };
    cout << "multiset size = " << mymultiset.size() << endl;
    cout << "multiset count(2) =" << mymultiset.count(2) << endl;

    //删除容器中所有值为 2 的元素
    int num = mymultiset.erase(2);
    cout << "删除了 " << num << " 个元素 2" << endl;
    //输出容器中存储的所有元素
    for (auto iter = mymultiset.begin(); iter != mymultiset.end(); ++iter) {
        cout << *iter << " ";
    }
    return 0;
}

  • 输出

multiset size = 7
multiset count(2) =3
删除了 3 个元素 2
1 3 4 5

参考:
1、C++ STL 容器库 中文文档
2、STL教程:C++ STL快速入门
3、https://www.apiref.com/cpp-zh/cpp/header.html
4、https://en.cppreference.com/w/cpp/container

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

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

相关文章

linux四剑客 grep awk sed find

Grep 过滤来自一个文件或标准输入匹配模式内容。 除了grep外&#xff0c;还有egrep、fgrep。egrep是grep的扩展&#xff0c;相当于grep -E。fgrep相当于grep -f&#xff0c;用的少。 Usage: grep [OPTION]… PATTERN [FILE]… 支持的正则描述-E&#xff0c;–extended-regexp…

爱智EdgerOS之深入解析VSCode的EdgerOS插件

一、安装插件 EdgerOS 插件是一个专门为应用开发者提供的在 EdgerOS 下提供应用构建、应用部署、应用更新等功能的插件&#xff0c;同时它还可以监视爱智应用的执行状态&#xff0c;方便开发者更好地调试应用。EdgerOS 插件需要在 VSCode 的 “拓展” 中下载安装&#xff0c;如…

vue-vue2和vue3的diff算法

核心要点 数据变化时&#xff0c;vue如何更新节点虚拟DOM 和 真实DOM 的区别vue2 diff 算法vue3 diff 算法 一、 数据变化时&#xff0c;vue如何更新节点 首先渲染真实DOM的开销是很大&#xff0c;比如有时候我们修改了某个数据且修改的数据量很大时&#xff0c;此时会频繁的…

自学编程的5大误区,早知道早避坑,过来人的宝贵经验

前言 有的人自学很快&#xff0c;几乎一个多月就能掌握一门技术&#xff0c;而有的人苦苦坚持&#xff0c;最后还是半途而废&#xff0c;很大的原因就在于在学习的时候掉进了一些误区没能走出来。 今天我们就来讲讲自学编程常见的5大误区&#xff0c;避开这些误区我们定能在自…

【Java Web】014 -- SpringBoot原理(配置优先级、Bean管理、SpringBoot原理)

目录 一、配置优先级 1、配置&#xff08;3种&#xff1a;.properties、yml、yaml&#xff09; ①、配置文件优先级 ②、如何指定Java系统属性和命令行参数 ③、5种配置文件的优先级 二、Bean管理 1、获取bean&#xff08;3种方法&#xff09; 2、bean作用域&#xff08;5种&am…

Arduino开发之如何连接超声波模块?

文章目录0、引言1、超声波模块说明2、代码编写3、功能演示0、引言 在利用Arduino开发过程中&#xff0c;若需知道设备与周围环境的距离&#xff0c;可利用超声波模块测量短程距离&#xff0c;使运动设备感知周围环境。本文在【Arduino如何进行开发&#xff1f;】基础上&#xf…

探索树形数据结构,通识树、森林与二叉树的基础知识(专有名词),进一步利用顺序表和链表表示、遍历和线索树形结构

树与二叉树 1.树 1.树形结构(非线性结构) 结点之间有分支&#xff0c;具有层次关系 树的定义&#xff1a; 树(tree)是n(n≥0)个有限集。 若n 0&#xff0c;则称为空树&#xff1b; 若n > 0&#xff0c;则它满足如下两个条件&#xff1a; 有且仅有一个特定的称为根(Ro…

NIFI大数据进阶_Json内容转换为Hive支持的文本格式_实际操作_02---大数据之Nifi工作笔记0032

然后首先我们来看一下hdfs中的数据的格式可以看到,还是json的格式对吧 而且也没有回行 然后我们来操作,首先添加一个evaluateJsonPath处理器 可以看到找到这个处理器 添加以后,我们去配置 ​​​​​​​ 点击去配置evaluateJsonPath处理器 可以看到首先我们destination这里配…

Rancher部署K8s集群

一、集群配置 服务器CPU内存磁盘操作系统k8s-master16核16G60GCentOS Linux release 7.5.1804k8s-node-116核16G60GCentOS Linux release 7.5.1804k8s-node-216核16G60GCentOS Linux release 7.5.1804 Rancher version : 2.6.3 二、环境初始化 所有服务器均执行一遍 1、将…

如何在矩池云上部署 Carla,模拟自动驾驶

简介 Carla 是一款基于 Python 编写和 UE&#xff08;虚幻引擎&#xff09;的开源仿真器&#xff0c;用于模拟自动驾驶车辆在不同场景下的行为和决策。它提供了高度可定制和可扩展的驾驶环境&#xff0c;包括城市、高速公路和农村道路等。Carla 还提供了丰富的 API 和工具&…

vscode中的配置

首先&#xff0c;运行或调试某文件&#xff0c;需要该文件是活动文件&#xff08;当前打开的文件&#xff09;。 下面依次介绍tasks.json和launch.json的配置参数。 tasks.json 1.tasks.json的用途 用于指定编译器和链接文件等。默认路径在.vscode下面。 2.如何打开一个tas…

springboot+Mybatis项目搭建教学(controller、service、dao、entity),并写一个简单的接口

创建一个springboot的项目 首先我们需要新建一个文件夹对吧&#xff0c;这里就不展示了&#xff0c;然后我们用IDEA打开这个文件夹&#xff0c;是这样的 新建一个模块 然后按照这里的进行选择 模块名字是自己随便起的&#xff0c;命名在这里时无关紧要的&#xff0c;然后我…

Python实现Imagenet数据集的合并和拆分

Python实现Imagenet数据集的合并和拆分 1. 合并Imagenet 任务需求 文件夹形式为一个数据集MyImagenet&#xff0c;路径为/home/lihuanyu/code/03AdaBins/img_data/MyImagenet/val&#xff0c;val文件夹又有若干的类别子文件夹&#xff0c;子文件夹是每一个类别的图片&#xf…

数据结构_第十一关:二叉树的链式结构

目录 1.二叉树链式结构的实现 1.1前置说明 1.2二叉树的遍历 1.3二叉树遍历的实现&#xff1a; 1&#xff09;先序遍历、中序遍历、后续遍历代码如下 2&#xff09;层序遍历&#xff1a; 1.4结点个数以及高度的计算 1&#xff09;求二叉树的总节点&#xff1a; 2&#…

阿里张勇:所有行业都值得用大模型重新做一遍!

‍数据智能产业创新服务媒体——聚焦数智 改变商业“2023阿里云峰会”于4月11日在北京国际会议中心隆重召开&#xff0c;本次峰会以" 与实俱进 为创新提速&#xff01;"为主题&#xff0c;阿里巴巴集团董事会主席兼首席执行官张勇、阿里云智能集团首席技术官周靖人、…

Python机器学习:适合新手的8个项

再多的理论也不能代替动手实践。教科书和课程会让你误以为精通&#xff0c;因为材料就在你面前。但当你尝试去应用它时&#xff0c;可能会发现它比看起来更难。而「项目」可帮助你快速提高应用的 ML 技能&#xff0c;同时让你有机会探索有趣的主题。此外&#xff0c;你可以将项…

java mysql高校教学成果管理系统dzkfY3程序

1.用户管理模块&#xff1a; 该模块包括注册用户管理和系统用户管理&#xff0c;系统用户主要是普通管理员&#xff0c;对用户信息进行管理&#xff0c;只有注册用户才可在该系统上进行相应的操作。用户对个人信息可进行修改&#xff1b;管理员可对自己的个人信息进行维护&…

Java线程系列详解

一&#xff0c;基本概念 进程&#xff1a; 程序是计算机指令的集合&#xff0c;它以文件形式存储在磁盘上&#xff0c;而进程就是一个执行中的程序&#xff0c;而每一个进程都有其独立的内存空间和系统资源。线程&#xff1a; 线程运行在进程中&#xff0c;不能独立存在。线程…

2019年 团体程序设计天梯赛——题解集

前言&#xff1a; Hello各位童学大家好&#xff01;&#x1f60a;&#x1f60a;&#xff0c;茫茫题海你我相遇即是缘分呐&#xff0c;或许日复一日的刷题已经让你感到疲惫甚至厌倦了&#xff0c;但是我们真的真的已经达到了我们自身极限了吗&#xff1f;少一点自我感动&#xf…

城乡供水一体化信息化系统-城乡供水一体化

建设方案 城乡供水一体化信息化系统是运用云计算、大数据等信息化手段&#xff0c;借助在线监测设备&#xff0c;并依托“供水信息化平台”&#xff0c;实时感知供水系统的运行状态&#xff0c;实现对农村供水工程远程监控、在线监测、实时预警、智慧监管。 系统功能 水源地监测…