STL补充:STL中遵循的左闭右开原则/STL随机访问

news2024/9/23 13:25:49

文章目录

    • 左闭右开原则
      • 示例:
      • 示例中erase的用法
      • 不能写成s.erase(s.begin()+left)的原因
    • STL中支持随机访问的迭代器

左闭右开原则

在 C++ 中,容器(如 vectorsetmap 等)的迭代器都遵循左闭右开的原则。

也就是说,对于任何容器 cc.begin() 返回的迭代器指向容器的第一个元素,而 c.end() 返回的迭代器指向容器的“尾后”元素,也就是最后一个元素的下一个位置

所以, c.end() 不指向任何有效元素,不能解引用得到元素,通常只作为范围结束的标志。

例如,下面的代码是遍历一个 vector 的标准方法:

vector<int> v = {1, 2, 3, 4, 5};
for(auto it = v.begin(); it != v.end(); ++it) {
    cout << *it << endl;
}

在这个例子中,v.begin() 返回的迭代器指向第一个元素 1v.end() 返回的迭代器指向尾后位置。我们一直迭代到 it 等于 v.end() 时停止,这时 it 已经不再指向任何有效元素。这就是左闭右开原则在 C++ 容器中的应用。

如果我们需要访问最后一个元素,应该用**反向迭代器*s.rbegin()**来实现。

示例:

//leetcode 6911.不间断子数组
class Solution {
public:
    long long continuousSubarrays(vector<int> &nums) {
        long long ans = 0;
        multiset<int> s;
        int left = 0;
        for (int right = 0; right < nums.size(); right++) {
            s.insert(nums[right]);
            while (*s.rbegin() - *s.begin() > 2){
                s.erase(s.find(nums[left]));
                left++;
            }
            ans += right - left + 1;
        }
        return ans;
    }
};

s.rbegin() 返回的是一个反向迭代器它指向的是容器中的最后一个元素。反向迭代器的工作方式和普通迭代器正好相反:递增反向迭代器会移动到前一个元素,递减反向迭代器会移动到后一个元素。因此,s.rbegin() 实际上给了我们一个方便的方式来访问容器中的最后一个元素

在上面这个例子中,由于multiset是一个自动排序的set容器,因此**s.begin()s.rbegin() 分别返回指向 multiset 中最小元素和最大元素的迭代器**。因为这些方法返回的是迭代器,所以我们需要使用 * 操作符来解引用迭代器,得到它们实际指向的值。

示例中erase的用法

在 C++ 的 STL 中,erase 是用来删除容器中的元素的成员函数,multiseterase 函数可以接收两种类型的参数:

  1. 一个值:erase(val) 会删除 multiset所有等于 val 的元素。
  2. 一个迭代器:erase(iterator) 会删除迭代器指向的元素

比如,在示例中,s.erase(s.find(nums[left++]))erase 函数接收的是一个迭代器。

find 函数在 multiset 中寻找给定值的元素,如果找到,返回指向这个元素的迭代器;如果没有找到,返回 s.end()。然后 s.erase 删除这个迭代器指向的元素

在示例代码中,使用迭代器而不是值作为参数,是因为我们只想删除窗口最左边的元素,而不是删除所有等于这个值的元素。如果直接使用值作为参数,s.erase(nums[left++]) 就会删除所有等于 nums[left++] 的元素。所以需要使用 find 函数找到最左边的元素的迭代器,并传递给 erase 函数。

不能写成s.erase(s.begin()+left)的原因

在使用vector容器的时候,迭代器支持随机访问的操作。例如下图:

在这里插入图片描述
但在 std::multiset 中,不能这么使用。

因为**std::multiset 中的迭代器只支持单向(forward)或双向(bidirectional)的操作,而不支持随机访问**。也就是说,不能直接加一个偏移量到 begin()。会出现下图报错。

在这里插入图片描述
如果想从 std::multisetbegin() 开始移动到某个位置,需要使用迭代器的 ++ 操作,比如:

auto it = s.begin();
std::advance(it, left);  // 或者使用 for 循环 left 次执行 ++it
s.erase(it);

以上代码中,std::advance 函数可以用于在输入迭代器上进行前进操作。但注意这个操作的复杂度是线性的,因为 std::multiset 的迭代器不支持随机访问,所以这可能会影响算法效率。

在不支持随机访问的容器内,最直接的删除元素方式

set1.erase(set1.find(a));//set中删除元素a,使用find先得到迭代器

STL中支持随机访问的迭代器

在C++的标准模板库(STL)中,std::vectorstd::dequestd::array,和std::string是支持随机访问的容器,它们的迭代器都支持随机访问

这意味着可以直接在这些容器的迭代器上加上一个偏移量来访问元素。以下是一些示例:

1. std::vector:

std::vector<int> v = {1, 2, 3, 4, 5};
auto it = v.begin() + 2;  // 现在 it 指向元素 3
v.erase(it);  // 删除元素 3

2. std::deque:

std::deque<int> d = {1, 2, 3, 4, 5};
auto it = d.begin() + 2;  // 现在 it 指向元素 3
d.erase(it);  // 删除元素 3

3. std::array:

std::array<int, 5> a = {1, 2, 3, 4, 5};
auto it = a.begin() + 2;  // 现在 it 指向元素 3
// array 不支持 erase 操作,但你可以通过迭代器访问元素

4. std::string:

std::string s = "hello";
auto it = s.begin() + 2;  // 现在 it 指向字符 'l'
s.erase(it);  // 删除字符 'l'

需要注意的是,不是所有的容器都支持随机访问。例如 std::liststd::setstd::map 等容器的迭代器只支持前向或双向访问,不能在这些迭代器上直接加上一个偏移量。同样,这些容器中的 erase 函数通常也接受一个迭代器参数,但这个迭代器不能通过加偏移量来得到

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

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

相关文章

微服务- Eureka 注册

1. 首先从结构方面来说 单体架构&#xff1a;比较适合用于小型项目&#xff08;像一些学生管理系统&#xff09;&#xff0c;简单方便&#xff0c;高度耦合 分布式架构&#xff1a;松耦合&#xff0c;扩展性好&#xff0c;但架构复杂&#xff0c;难度大&#xff0c;适合大型互联…

CIO40---3个亿数字化供应链实战

2019年某天&#xff0c;我被总裁叫到办公室&#xff0c;我当是VP A&#xff1a;企业情况 一家A股上市 市值150亿&#xff0c;年销售50亿&#xff0c; 员工4000人&#xff0c;全国4个工厂 家庭企业&#xff0c;高管老人多 经销商模式&#xff0c;总代模式&#xff0c;工程…

unserialize3

看着这个源码长度&#xff0c;就觉着比较简单 本题就一个__wakeup方法需要绕过&#xff0c;但是不对哦没有提示也不知道该参数得多少呀 本来都要复制进编译器写了&#xff0c;发现源码闭合有点问题&#xff0c;可能是做了隐藏 解题步骤 实在找不到了&#xff0c;就尝试了一下fl…

81、基于STM32单片机的颜色识别 TCS3200 RGB 检测系统设计(程序+原理图+PCB源文件+参考论文+开题报告+任务书+设计资料+元器件清单等)

摘 要 随着现代工业生产向高速化、自动化方向的发展&#xff0c;色彩识别广泛应用于各种工业检测和自动控制领域&#xff0c;而生产过程中长期以来由人眼起主导作用的颜色识别工作将越来越多地被相应的颜色传感器所替代。如&#xff1a;各种物体表面颜色识别&#xff08;产品包…

什么是三极管推挽电路

这是一个三极管推挽电路&#xff0c;上面是一个NPN的三极管&#xff0c;下面是一个PNP的三极管。 当输入信号为VCC时&#xff0c;上面的三极管导通&#xff0c;下面的三极管截止&#xff0c;输出信号为VCC-0.7V&#xff0c;这个0.7V就是上面NPN三极管BE间的导通压降 当输入信号…

Spring Bean 作用域的定义

在 Spring 配置中&#xff0c;我们可以通过 scope 属性来定义 Spring Bean 的作用域&#xff0c;可以接受 5 个内建的值&#xff0c;分别代表 5 种作用域类型&#xff0c;下面给大家详细总结一下&#xff1a; 1、singleton&#xff0c;用来定义一个 Bean 为单例&#xff0c;也…

【MATLAB第50期】基于MATLAB的RELM-LOO多输入单输出回归分类预测算法与RELM及ELM进行对比

【MATLAB第50期】基于MATLAB的RELM-LOO多输入单输出回归&分类预测算法与RELM及ELM进行对比 引言 RELM-LOO即通过LOO计算效率方法对其RELM模型正则化C系数进行寻优。 对于进化算法寻优来说&#xff0c; 结果更稳定。 可参考以下文献&#xff1a; [1] Shao Z , Er M J , W…

小红书测评类产品种草文案怎么写?品牌方必看

小红书逐渐成为了越来越多年轻人购物和分享的主流平台。测评类产品的种草文案尤为重要&#xff0c;因为它可以帮助消费者更好地了解产品的性能、使用方法以及适用场景&#xff0c;从而为购物决策提供参考。这个时候将某个产品植入进去&#xff0c;就会更容易被用户所接受&#…

C++高级编程01

目录 1、双冒号作用域运算符 2、namespace命名空间 3、using声明以及using编译指令 using 声明 4、C对C语言的增强 4、const链接属性 5、const分配内存情况 6、尽量用const代替define 7、引用 1、双冒号作用域运算符 ::代表作用域 如果前面什么都不添加 代表全局作用…

K8S资源控制器管理

资源控制器 1 资源控制器1.1 控制基础1.1.1 控制原理1.1.2 控制对象 1.2 标签选择器1.2.1 标签基础1.2.2 标签选择器 1.3 副本控制器1.3.1 RC&RS1.3.2 Deploy基础1.3.3 Deploy进阶1.3.4 DaemonSet1.3.5 任务控制器 1.4 监视控制器1.4.1 metrics服务1.4.2 HPA实践 1 资源控制…

Git 推送教程

一般 add commit push即可。Git全流程&#xff1a; git init #初始化仓库 git add .文件名 #添加文件&#xff0c;添加全部文件可以直接写. git commit -m "信息" #提交到本地仓库 git remote add origin 远程仓库地址 #链接远程仓库&#xff0c;创建主分支 git p…

【每日一题】2. 两数相加

【每日一题】2. 两数相加 2. 两数相加题目描述解题思路 2. 两数相加 题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一…

MySQL的体系架构

文章目录 前言MySQL的Server层MySQL的存储引擎1&#xff09;InnoDB 存储引擎2&#xff09;MyISAM 存储引擎3&#xff09;Memory 存储引擎 前言 在学习一种事务之前&#xff0c;我们需要先了解事物的基本组成结构&#xff0c;清楚了事物的基本组成结构之后&#xff0c;我们才能…

QCC51XX---chain是什么?

QCC51XX---系统学习目录_嵌入式学习_force的博客-CSDN博客 高通的DSP对很多人来说还是比较难以理解与操作的,DSP里最基本的是要认识音频的处理链路,也就是平台中的chain。他是由多个模块(operator)连接起来的,连接的方法sink和earbud有些不同,这里会从6.x开始sink的chain…

shell判断程序是否运行

一、需求 服务部署在linux上&#xff0c;要求服务器上的服务可以一直保持正常运行 二、问题 在linux上部署的微服务&#xff0c;不知道什么原因过一段时间就自己停掉了&#xff0c;无法启动。 三、解决办法 添加angle守护进程&#xff0c;通过定时执行脚本来判断程序是否运行…

AI 绘画 - 建筑绘图辅助设计之模型训练

前情提要 2023-06-18 周日 杭州 小雨 小记: 昨天搞的好累&#xff0c;10点左右就想着先躺一会儿&#xff0c;然后就睡过去了&#xff0c;很奇怪&#xff0c;如果进行 AI 绘画&#xff0c;晚上就会做很奇怪的梦&#xff0c;说不上来的那种感觉&#xff0c;就是莫名的不舒服。 …

微信怎么能自动回复?

有些小伙伴可能有多个微信号来进行业务活动&#xff0c;一天收到的信息太多&#xff0c;眼花缭乱&#xff0c;回复不过来&#xff0c;就想在微信可不可以有个自动回复消息&#xff0c;就可以通过自动回复引导用户看到想让他们看到的。这样就可以降低工作量的同时&#xff0c;提…

Hive Metastore 表结构

Hive MetaStore 的ER 图如下。 部分表结构和说明。 CTLGS(CATALOGS) catalogs 可以隔离元数据。默认只有1行。一个 CATALOG 可以有多个数据库。 mysql> DESC CTLGS; -------------------------------------------------------- | Field | Type | Null |…

判断关系属于哪一种范式(期末考试必看)

1NF&#xff08;第一范式&#xff09; 属性值是不可分的原子值 2NF&#xff08;第二范式&#xff09; R1NF&#xff0c;每个非主属性都完全函数依赖于R的候选键 3NF&#xff08;第三范式&#xff09; R1NF&#xff0c;每个非主属性都不传递依赖于 R的候选键 BCNF&#xff08;BC…

ubuntu修改主机名和用户名

参考文章&#xff1a; https://blog.csdn.net/fkmmmm/article/details/127333212 一、修改主机名 sudo vi /etc/hostname2、 sudo vi /etc/hosts3、 sudo reboot二、修改用户名 1、修改所有原用户名&#xff08;如果文件内没有原用户名则不用改 sudo vi /etc/sudoers 2、 s…