【044】深入探索STL:解密set与multiset容器的神秘力量

news2024/11/20 13:57:55

解密set与multiset容器的神秘力量

  • 引言
  • 一、set和 multiset容器概述
  • 二、set容器常用API
  • 三、multiset的常用API
  • 四、对组 pair
    • 4.1、概念
    • 4.2、创建对组 pair 的方式
  • 五、使用示例
    • 5.1、重定义排序规则
    • 5.2、队组pair的使用
  • 总结

引言


💡 作者简介:一个热爱分享高性能服务器后台开发知识的博主,目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。技能涵盖了多个领域,包括C/C++、Linux、Nginx、MySQL、Redis、fastdfs、kafka、Docker、TCP/IP、协程、DPDK等。
👉
🎖️ CSDN实力新星、CSDN博客专家
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【043】解密C++ STL:深入理解并使用 list 容器

一、set和 multiset容器概述

STL(Standard Template Library)中的setmultiset是两种常用的关联容器,用于存储一组有序且唯一的元素。它们具有以下基本概念:

  1. set容器:

    • set是一个有序容器,其中的元素按照特定的排序准则进行排序。
    • 每个元素在set只能存在一次,重复的插入将无效
    • 使用二叉搜索树(红黑树)数据结构来实现元素的存储和检索,因此其插入、删除和查找操作的平均时间复杂度为O(logN),其中N是元素的数量。
    • set中的元素默认以升序排列,也可以自定义排序规则。
  2. multiset容器:

    • multisetset类似,但允许存储重复的元素
    • 元素在multiset中按照特定的排序准则进行排序,并且插入操作总是成功,不会检测重复元素。
    • set相比,multiset的插入、删除和查找操作的平均时间复杂度也是O(logN)。

这两种容器都提供了一系列的成员函数和迭代器来操作和访问元素,例如插入元素、删除元素、查找元素等。此外,它们还提供了丰富的算法和操作符重载来方便地处理容器中的元素。
在这里插入图片描述

注意:在使用setmultiset时,由于元素的有序性和二叉搜索树的特性,插入、删除和查找操作的时间复杂度相对于其他容器(如vectorlist)可能更高。

二、set容器常用API

下面是set容器的常用接口函数原型:

  1. 构造函数:
explicit set(const Compare& comp = Compare(), const Allocator& alloc = Allocator());
explicit set(const Allocator& alloc);
template <class InputIterator>
set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());
set(const set& other);
set(set&& other) noexcept;
  1. 插入和删除元素:
iterator insert(const value_type& value);
iterator insert(value_type&& value);
iterator insert(const_iterator hint, const value_type& value);
iterator insert(const_iterator hint, value_type&& value);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& key);
void erase(iterator first, iterator last);
void clear() noexcept;
  1. 访问元素和容量相关:
iterator find(const key_type& key);
const_iterator find(const key_type& key) const;
size_type count(const key_type& key) const;
bool empty() const noexcept;
size_type size() const noexcept;
  1. 迭代器相关:
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;

这里只列举了部分常用的接口函数原型,set容器还包含其他许多用于比较、交换、合并等操作的函数。此外,还可以通过迭代器对容器中的元素进行遍历和访问。

例如:下面是set容器的upper_boundlower_boundequal_range接口函数的原型:

  1. upper_bound函数原型:
iterator upper_bound(const key_type& key);
const_iterator upper_bound(const key_type& key) const;
  1. lower_bound函数原型:
iterator lower_bound(const key_type& key);
const_iterator lower_bound(const key_type& key) const;
  1. equal_range函数原型:
std::pair<iterator, iterator> equal_range(const key_type& key);
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;

这些函数用于在set容器中进行元素搜索。它们根据元素的键值进行查找,并返回满足特定条件的迭代器或迭代器范围。

  • upper_bound函数返回一个迭代器,指向第一个大于给定键值的元素位置。
  • lower_bound函数返回一个迭代器,指向第一个不小于给定键值的元素位置。
  • equal_range函数返回一个包含两个迭代器的pair对象,分别表示与给定键值匹配的元素范围的起始和结束位置。

注意以上函数假设set容器中的元素已经按照严格弱排序的方式(默认是由小到大)进行了排序。
在这里插入图片描述

三、multiset的常用API

下面是multiset容器的所有接口函数的原型:

  1. 构造函数:
explicit multiset(const Compare& comp = Compare(), const Allocator& alloc = Allocator());
explicit multiset(const Allocator& alloc);
template <class InputIterator>
multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator());
multiset(const multiset& other);
multiset(multiset&& other) noexcept;
  1. 插入和删除元素:
iterator insert(const value_type& value);
iterator insert(value_type&& value);
iterator insert(const_iterator hint, const value_type& value);
iterator insert(const_iterator hint, value_type&& value);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& key);
void erase(iterator first, iterator last);
void clear() noexcept;
  1. 访问元素和容量相关:
iterator find(const key_type& key);
const_iterator find(const key_type& key) const;
size_type count(const key_type& key) const;
bool empty() const noexcept;
size_type size() const noexcept;
  1. 迭代器相关:
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
  1. lower_boundupper_boundequal_range接口函数的原型与set相同。

这些函数的作用和用法与set容器类似,但multiset容器允许存储重复的键值,因此在插入和删除元素时不会执行唯一性检查。其余的特性和接口函数与set相同。

四、对组 pair

对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有属性first和second模板: template <class T1, class T2> struct pair。

4.1、概念

STL(Standard Template Library)提供了一个名为pair的模板类,用于表示有序的、具有固定数量的数据元素对。pair模板类定义在 <utility> 头文件中。

pair模板类的定义如下:

template<class T1, class T2>
struct pair {
    typedef T1 first_type;    // 第一个元素类型
    typedef T2 second_type;   // 第二个元素类型

    T1 first;    // 第一个元素
    T2 second;   // 第二个元素

    // 构造函数
    template<class U, class V>
    pair(U&& x, V&& y);
    ...
};

pair类具有以下特性和功能:

  1. pair类包含公共的两个成员变量:firstsecond,分别存储第一个元素和第二个元素。

  2. 可以通过直接访问成员变量 firstsecond 来获取或修改元素的值。

  3. pair类支持复制构造函数、移动构造函数和赋值运算符重载。

  4. 参数化类型 T1T2 决定了 pair 可以存储的元素类型。可以是任何可复制、可比较和可分配内存的类型。

  5. pair 类还提供了方便的构造函数用于创建对象,并将传入的值分配给 firstsecond

  6. pair 类还支持比较操作符(如 ==!=<><=>=)的重载,用于比较两个 pair 对象之间的大小关系。

使用示例:

#include <iostream>
#include <utility>

int main() {
    std::pair<int, double> myPair(10, 3.14);

    std::cout << "First element: " << myPair.first << std::endl;
    std::cout << "Second element: " << myPair.second << std::endl;

    myPair.first = 20;
    myPair.second = 2.71;

    std::cout << "Modified first element: " << myPair.first << std::endl;
    std::cout << "Modified second element: " << myPair.second << std::endl;

    return 0;
}

输出结果:

First element: 10
Second element: 3.14
Modified first element: 20
Modified second element: 2.71

4.2、创建对组 pair 的方式

在STL中,创建pair对象有多种方式:

  1. 使用构造函数创建:
#include <utility>

std::pair<int, double> myPair(10, 3.14);
  1. 使用make_pair函数创建:
#include <utility>

auto myPair = std::make_pair(10, 3.14);
  1. 使用花括号初始化列表创建(C++11及以上版本):
#include <utility>

auto myPair = std::pair<int, double>{10, 3.14};
  1. 使用赋值运算符创建:
#include <utility>

std::pair<int, double> myPair;
myPair = std::make_pair(10, 3.14);

无论使用哪种方式创建pair对象,都要指定两个元素的类型,并提供对应数量的参数来初始化firstsecond成员变量。

五、使用示例

5.1、重定义排序规则

仿函数:重载函数调用运算符()的类。

class MyGreater
{
public:
	bool operator() (int v1, int v2){
		return v1>v2;
	}
};
void test(){
	// set<int,排序规则>sl;
	set<int,MyGreatersl;s1.insert(30);
	s1.insert(10);
	s1.insert(20);
	s1.insert(50);
	s1.insert(40);

}

set存放自定义数据必须修改排序

5.2、队组pair的使用

void test()
{
	set<int> sl;
	s1.insert(10);
	s1.insert(30);
	s1.insert(50);
	s1.insert(70);
	s1.insert(90);
	set<int> : : const_iterator ret;
	ret = s1 .lower_bound (50);
	if(ret!=s1.end( ) )
	{
		cout<<"下限为:"<<*ret<<endl;
	}
	ret = s1.upper_bound (50);
	if(ret! =s1.end())
	{
		cout<<"上限为:"<<*ret<<endl;
	}
	//以对组的方式存储上下限pair
	pair< set<int> : :const_iterator , set<int> ::const_iterator> pa;
	pa= s1.equal_range(50);
	if(pa.first != s1.end())
	{
		cout<<"下限为:"<<*(pa.first)<<endl;
	}
	if(pa.second != s1.end())
	{
		cout<<"上限为:"<<*(pa.second)<<endl;
	}

总结

  • set的特性是所有元素都会根据元素的键值自动被排序,set的元素即是键值又是实值。
  • set不允许两个元素有相同的键值。
  • set容器的迭代器是只读迭代器,不允许修改键值,会破坏set的内存布局。
  • multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。

在这里插入图片描述

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

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

相关文章

【GeoDa实用技巧100例】016:制作(三维)散点图

文章目录 一、散点图介绍二、加载实验数据三、散点图制作四、剔除回归样本五、3D散点图一、散点图介绍 散点图是一种以点的分布反映变量之间相关情况的统计图。根据散点图中各点的分布走向和密度,可以大致判断变量之间相互关系。根据反映变量的维度可分为二维(亦称2D)和三维(…

数据结构第六天(7.20)双向链表逆置

DoubleLink rev_double(DoubleLink L,int n) {if(LNULL||L->nextNULL)return L;DoubleLink pL;LL->next;p->nextNULL;DoubleLink t;printf("%d",n);for(int i0;i<n-1;i){tL;LL->next;t->nextp;p->prevt;t->prevNULL;pt;}return p; }

【kubernetes系列】flannel之vxlan模式原理

概述 在Kubernetes中要保证容器之间网络互通&#xff0c;网络至关重要。而Kubernetes本身并没有自己实现容器网络&#xff0c;而是而是借助CNI标准&#xff0c;通过插件化的方式自由接入进来。在容器网络接入进来需要满足如下基本原则&#xff1a; Pod无论运行在任何节点都可…

【Ubuntu18.04安装FileZilla】

Ubuntu18.04安装FileZilla 1 FileZilla简介2 安装方式3 使用方式3.1 连接FTP服务器3.1.1 快速连接3.1.2 通过站点管理器 1 FileZilla简介 FileZilla是自由开源、快速、可信赖的FTP客户端以及服务器端应用&#xff0c;具有多种特色、直观的接口。 特点&#xff1a;可控性、有条…

flutter android Webview 打开网页错误ERR_CLEARTEXT_NOT_PERMITTED 、 net:ERR_CACHE_MISS

当你在Flutter应用中尝试打开一个非安全连接的网页&#xff08;例如HTTP连接而不是HTTPS连接&#xff09;时&#xff0c;可能会遇到"ERR_CLEARTEXT_NOT_PERMITTED"错误。这是因为默认情况下&#xff0c;Android 9及更高版本禁止应用程序通过非安全的明文HTTP连接进行…

Lombok 使用教程

lombok 官网 Project Lombok 课程目标: 什么是lombok lombok的原理 lombok的常用注解 lombok的安装 引言 还记得刚刚接触java,学习面向对象时因为手写get,set,hashcode,equals等方法的痛苦吗? 还记得后来上手了Eclipse或Idea这样工具可以快速生成get,set等相关方法的兴奋吗? …

【如何训练一个中译英翻译器】LSTM机器翻译模型部署之ncnn(python)(五)

系列文章 【如何训练一个中译英翻译器】LSTM机器翻译seq2seq字符编码&#xff08;一&#xff09; 【如何训练一个中译英翻译器】LSTM机器翻译模型训练与保存&#xff08;二&#xff09; 【如何训练一个中译英翻译器】LSTM机器翻译模型部署&#xff08;三&#xff09; 【如何训…

数据结构和算法——桶排序和基数排序(图示、伪代码、多关键字排序,基数排序代码)

目录 桶排序 图示 伪代码 时间复杂度 基数排序 多关键字排序 代码&#xff08;C语言&#xff09; 次位优先 主位优先 桶排序 假设有N个学生&#xff0c;他们的成绩是0到100之间的整数&#xff08;于是有M101个不同的成绩值&#xff09;。如何在线性时间内将学生按成绩…

什么是在线帮助中心?

随着企业越来越注重客户体验和服务质量&#xff0c;建立一个完善的在线帮助中心已经成为企业不可或缺的一部分。在线帮助中心可以帮助客户解决各种问题&#xff0c;从而提升客户满意度和忠诚度。而Baklib作为一款优雅的云知识库构建平台&#xff0c;提供了一种简单高效的方式来…

网页聊天室项目性能测试报告

文章目录 一 概述二 测试环境三 测试内容及方法四 GUI测试步骤五 简单数据写入器 HTML报告DashBoard六 结果分析七 性能优化方案 一 概述 1.1 目的 本测试报告为网页聊天室的性能测试报告&#xff0c;目的在于总结性能测试阶段的学习以及分析测试结果&#xff0c;描述网站是否…

创建线程的两种方式

一、线程相关概念 程序&#xff1a;完成特定任务&#xff0c;用某种语言编写的一组指令的集合。进程&#xff1a;运行起来的程序就是进程。进程运行时&#xff0c;操作系统需要为该进程分配内存空间。进程是一个动态过程&#xff0c;有产生、存在和消亡的过程。线程&#xff1…

osg earth中加载标签并设置文字 以及使用注意事项

osgearth中加载标签并设置文字 //头文件 #include <osgEarthAnnotation/PlaceNode> #include <osgEarthSymbology/Style> #include <osgEarth/MapNode> osgEarth::GeoPoint position(m_mapnode->getMapSRS(), lon, lat, 0, osgEarth::AltitudeMode::ALTM…

数据驱动商业合作:企业联系方式查询API在市场中的角色与作用

摘要 在当今数字化商业环境中&#xff0c;企业间的商务合作和合作伙伴关系构建变得更加重要。为了有效推进商业拓展和建立持久合作&#xff0c;企业需要快速、准确地获取潜在合作伙伴的联系方式。本文将深入探讨企业联系方式查询 API 在市场中的角色与作用&#xff0c;以及它如…

JetBrains全家桶:如何自定义实现类TODO注释?

文章目录 效果图具体方法参考文献 效果图 TODO注释大家应该都用过&#xff0c;在注释开头打上TODO的话&#xff0c;软件下方的TODO选项卡里就可以自动筛选出你打了TODO的注释&#xff0c;你可以点击里面对应的注释来实现快速跳转。 jetbrains全家桶&#xff08;如Pycharm、Int…

LKT(LCS)系列IIC接口加密芯片

调试常见问题&#xff08;一&#xff09; 1.加密芯片的数据交互协议是什么格式&#xff1f; 发送时&#xff1a;地址两字节数据长度&#xff08;后续数据的长度&#xff09;后续数据内容。Eg.50 0005 0084000008。接收时&#xff1a;地址两字节数据长度&#xff08;后续数据的…

万字长文详解Webpack5高级优化

本文从 4 个角度对 webpack 和代码进行了优化&#xff1a; 1.提升开发体验 使用 Source Map 让开发或上线时代码报错能有更加准确的错误提示。 2.提升打包构建速度 使用 HotModuleReplacement 让开发时只重新编译打包更新变化了的代码&#xff0c;不变的代码使用缓存&#xff…

Github Flow工作流简单介绍(以部署为中心的开发模式)

前言 这篇文章主要介绍Github Flow的理念&#xff0c;以下内容来源于《Github入门与实践》。 Github Flow是以部署为中心的开发模式&#xff0c;通过简单的规则&#xff0c;持续高速且安全地进行部署。而Gitflow则是以发布为中心的分支管理模型&#xff0c;它提供了一种更灵活…

【Docker】Docker容器编排

目录 一、Docker Compose1.2Docker Compose 环境安装1.3 YAML 文件格式及编写注意事项2.3 Docker Compose配置常用字段2.4 Docker Compose 常用命令 二、Docker Compose实验2.1编写Nginx的Dockerfile脚本2.2编写MySQL&#xff0c;Dockerfile脚本2.3编写PHP&#xff0c;Dockerfi…

QT样式表qss中的长度单位px/pt/%/em/ex/mm/in等

以下是从CSS里抄来的。QSS只能支持其中一部分。 1、px&#xff1a;像素(Pixel),相对于设备的长度单位&#xff0c;像素是相对于显示器屏幕分辨率而言的。譬如&#xff0c;WONDOWS的用户所使用的分辨率一般是96像素/英寸。而MAC的用户所使用的分辨率一般是72像素/英寸。 像素&a…

在培训班里学IT技术是否有用?和大家分享相关IT培训班里五大常见宣传手法、相关优势与实际效果

目录 Introduction 引言IT培训班常见宣传手法培训班的优势如何评判IT培训班的效果与质量除IT培训班之外的学习渠道总结其它资料下载 Introduction 引言 随着信息技术的飞速发展&#xff0c;学习IT技术成为许多人追求职业发展和个人兴趣的重要途径。从软件开发、数据科学到人工…