《C++ Primer》第10章 算法(二)

参考资料:

  • 《C++ Primer》第5版
  • 《C++ Primer 习题集》第5版

10.4 再探迭代器(P357)

除了为每个容器定义的迭代器外,头文件 iterator 中还定义了额外的几种迭代器:

  • 插入迭代器(insert iterator):这些迭代器被绑定到一个容器上,可以向容器中插入元素
  • 流迭代器(stream iterator):这些迭代器被当顶到输入或输出流上,可用来遍历所关联的 IO 流。
  • 反向迭代器(reverse iterator):除 forward_list 外的所有标准库容器都有反向迭代器。
  • 移动迭代器(move iterator):用于移动元素的迭代器。

10.4.1 插入迭代器(P358)

插入器是一种迭代器适配器,接受一个容器,生成一个迭代器,能实现向容器中插入元素:

9c85b4e5133a340d1339db1dfc539a8

插入迭代器有三种类型,区别在于插入元素的位置:

  • back_inserter :使用 push_back
  • front_inserter :使用 push_front
  • inserter :使用 insert ,第二个参数为指向给定容器的迭代器。
vector<int> vi = { 0,1,2,3 };
list<int> v1, v2;
// 注意体会inserter和front_inserter的区别
auto it1 = inserter(v1, v1.begin());
auto it2 = front_inserter(v2);
for (auto i : vi) it1 = i, it2 = i;
for (auto i : v1) cout << i << ' ';    // 输出0 1 2 3
cout << endl;
for (auto i : v2) cout << i << ' ';    // 输出3 2 1 0

10.4.2 iostream迭代器(P359)

这部分不是很懂

流迭代器将对应的流当作一个特定类型元素的序列。创建一个流迭代器时,必须指定迭代器要读写的类型。

istream_iterator操作

a1ce62b884ddad959dfa85308164973

istream_iterator 通过 >> 来读取流,所以其要读取的数据类型必须定义了 >> 运算符:

istream_iterator<int> int_it(cin);    // 从cin读取int
istream_iterator<int> eof;    // 定义尾后迭代器
// 
vector<int> vi(int_it, eof);

使用算法操作流迭代器

istream_iterator<int> in(cin), eof;
cout << accumulate(in, eof, 0) << endl;

istream_iterator允许懒惰求值

当我们将一个 istream_iterator 绑定到一个流时,标准库不保证迭代器立即从流读取数据,具体实现可以知道我们使用迭代器时才读取读取数据。

ostream_iterator操作

94139cc852820f4982a9b3f21ef7c92

我们可以对具有 << 的类型定义 ostream_iterator 。在创建 ostream_iterator 时,我们可以提供第二个参数,类型为 C 风格字符串,在输出每个元素后都会打印此字符串。必须ostream_iterator 绑定到一个流。

此处应有图片

vector<int> vi = { 1,2,3,4,5 };
ostream_iterator<int> out(cout, ", ");
for (auto i : vi) {
	*out++ = i;
}
cout<<endl;
// 输出:1, 2, 3, 4, 5,

简单写法:

copy(vi.begin(), vei.end(), out);
cout<<endl;

10.4.3 反向迭代器(P363)

除了 forward_list 外,其他容器都支持反向迭代器:

vector<int> vi = { 1,2,3,4,5 };
for (auto r_iter = vi.crbegin(); r_iter != vi.crend(); r_iter++) {
	cout << *r_iter << ' ';
}
// 输出5 4 3 2 1

利用反向迭代器和 sort 实现降序排序:

sort(vi.rbegin(), vi.rend());

反向迭代器需要递减运算符

反向迭代器的实现依赖于普通迭代器的 -- 运算符,除 forward_list 外,标准库中的所有容器都同时支持递增和递减操作。

反向迭代器和其他迭代器间的关系

假设我们有一个名为 linestring ,保存着一个逗号分隔的单词序列:

string line("FIRST,MIDDLE,LAST");

如果我们想要打印第一个单词,使用 find 可以很容易实现:

auto comma = find(line.cbegin(), line.cend(), ',');
cout << string(line.cbegin(), comma) << endl;    // 输出FIRST

如果我们想要打印最后一个单词,可以借助反向迭代器:

auto rcomma = find(line.crbegin(), line.crend(), ',');
cout << string(line.crbegin(), rcomma) << endl;    // 输出TSAL

可以发现,使用反向迭代器会导致我们的实际输出也是反过来的,所以我们需要使用 reverser_iteratorbase 函数成员,将反向迭代器转变成正向迭代器:

cout << string(rcomma.base(), line.cend()) << endl;    // 输出LAST

这里需要注意,反向迭代器 rcomma 指向 ',' ,而 rcomma 对应的普通迭代器 rcomma.base() 指向 'L' ,这一设计反映了“左闭右开区间”的特性:

95d215824a96d6f8ff0510b26ab0411

10.5 泛型算法结构(P365)

算法所要求的迭代器操作可以分为 5 个迭代器类别(iterator category):

635e475bc060fa70ae8b74e8d4cb4bc

10.5.1 5类迭代器(P365)

C++ 标准指明了算法的每个迭代器参数的最小类别,向算法传递一个能力更差的迭代器会产生错误

对于向算法传递错误类别迭代器的问题,很多编译器不会给出警告信息。

迭代器类别

输入迭代器(input iterator):可以读取序列中的元素,必须支持:

  • 用于比较两个迭代器==!=
  • 用于推进迭代器的前置和后置 ++
  • 用于读取元素的解引用运算符 * ,解引用只会出现在赋值运算符的右侧
  • 箭头运算符 ->

对于一个输入迭代器,*it++ 保证是有效的,但递增后可能导致其他指向流的迭代器失效,导致不能保证输入迭代器的状态可以保存下来用来访问元素。因此,输入迭代器只适用于单遍扫描算法。istream_iterator 是一种输入迭代器。

输出迭代器(output iterator):只写而不读元素,必须支持:

  • 用于推进迭代器的前置和后置 ++
  • 解引用运算符 * ,解引用只会出现在赋值运算符的左侧

输出迭代器只能用于单遍扫描算法,ostream_iterator 是一种输出迭代器。

前向迭代器(forward iterator):只能在序列中沿一个方向移动,可以读写元素,支持所有输入和输出迭代器的操作,可以多次读写同一个元素。因此,前向迭代器可以用于多遍扫描算法,forward_list 上的迭代器是前向迭代器。

双向迭代器(bidirectional iterator):可以双向移动,支持前向迭代器所有操作,支持前置和后置 -- 运算符。除 forward_list 外,所有标准库容器都提供符合双向迭代器要求的迭代器。

随机访问迭代器(random-access iterator):提供在常量时间内访问序列内任意元素的能力。除支持双向迭代器的所有功能,还支持:

  • 用于比较两个迭代器相对位置关系的运算符 >>=<<=
  • 迭代器和一个整数值的加减运算 ++=--=
  • 用于两个迭代器的减法运算符,得到两个迭代器的距离。
  • 下标运算符 iter[n] ,与 *(iter[n]) 等价。

arraydequestringvector 的迭代器都是随机访问迭代器,访问内置数组元素的指针也是。

10.5.2 算法形参形式(P367)

大多数算法具有如下 4 种形式之一:

alg(beg, end, args);
alg(beg, end, dest, args);
alg(beg, end, beg2, args);
alg(beg, end, beg2, end2, args);

begend 表示算法操作的输入范围。

接受单个目标迭代器的算法

dest 参数表示算法写入的目的位置的迭代器,并假定目标空间足够容纳写入的数据。比较常见的情况是,dest 绑定到一个插入迭代器或 ostream_iterator

接受第二个输入序列的算法

接受单独 beg2beg2end2 的算法用这些迭代器表示第二个输入范围 ,并假定 beg2 开始的范围至少begend 的范围一样大。

10.5.3 算法命名规范(P368)

一些算法使用重载形式传递一个谓词

unique(beg, end);
unique(beg, end, comp);

_if版本的算法

find(beg, end, val);
find_if(beg, end, pred);

由于可能产生重载歧义,所以标准库选择提供不同名字而非重载。

区分拷贝元素的版本和不拷贝的版本

reverse(beg, end);
reverse_copy(beg, end, dest);
vector<int> v1 = { 0,1,2,3,4,5 };
vector<int> v2;
// 同时提供_copy和_if版本
remove_copy_if(v1.begin(), v1.end(), back_inserter(v2),
    [](int i) {return i % 2; });
for (auto i : v1) cout << i << ' ';    // 输出0 1 2 3 4 5
cout << endl;
for (auto i : v2) cout << i << ' ';    // 输出0 2 4

10.6 特定容器算法(P369)

链表类型 listforward_list 定义了几个成员函数形式的算法:

3a7a5e75cd04504e75d58ae3a565dde 13c474e99772158945fc1406e0d2d1b

由于通用版本的 sort 要求随机访问迭代器,所以链表类型 listforward_list 只能使用专用版本;其他算法的通用版本虽然可以用于 listforward_list ,但这些算法需要交换序列中的元素,而链表可以通过改变元素间的链接方式实现交换,所以专用版本的算法效率往往更高。

splice成员

该算法是链表类型独有的:

73283381abaeef91df8024611e7a099

链表特有操作会改变容器

通用算法不会改变容器,而链表特有版本会改变底层容器。

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

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

相关文章

echarts折线图的线呈现动态效果

效果如图 let yData [222, 932, 66, 934, 111, 333, 0],xData ["测1", "测2", "测3", "测4", "测5", "测6", "测7"],datacoords [{coords: [],},];for (var i 0; i < xData.length; i) {datacoo…

Python streamlit指南,构建令人惊叹的可视化Web界面!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在当今数据驱动的世界中&#xff0c;构建交互式、美观且高效的数据可视化应用变得至关重要。而Streamlit&#xff0c;作为Python生态系统中为开发者提供了轻松创建Web应用的利器。 本文将深入探讨Streamlit的方…

SS8812T 36V/1.6A 两通道 H 桥驱动芯片 替代DRV8812

SS8812T 为打印机和其它电机一体化应用提 供一种双通道集成电机驱动方案。 SS8812T 有两 路 H 桥驱动&#xff0c;每个 H 桥可提供最大输出电流 1.6A (在 24V 和 Ta 25C 适当散热条件下)&#xff0c;可驱动两 个刷式直流电机&#xff0c;或者一个双极步进电机&#xff0…

分支和循环

通常来说&#xff0c;C语言是结构化的程序设计语言&#xff0c;这里的结构包括顺序结构、选择结构、循环结构&#xff0c;C语言能够实现这三种结构&#xff0c;如果我们仔细分析&#xff0c;我们日常生活中所见的事情都可以拆分为这三种结构或者它们的组合。 下面我会仔细讲解我…

代理模式 1、静态代理 2、动态代理 jdk自带动态代理 3、Cglib代理

文章目录 代理模式1、静态代理2、动态代理jdk自带动态代理 3、Cglib代理 来和大家聊聊代理模式 代理模式 代理模式&#xff1a;即通过代理对象访问目标对象&#xff0c;实现目标对象的方法。这样做的好处是&#xff1a;可以在目标对象实现的基础上&#xff0c;增强额外的功能操…

STM32 CUBEIDE Outline is disabled due to scalability mode

项目场景&#xff1a; 问题描述 Outline is disabled due to scalability mode 看不到函数 解决方案&#xff1a;

QT 项目中添加文件夹(分类文件)

为了更方便的整理项目的文件&#xff0c;添加文件夹把文件进行分类。 1.首先在项目文件中创建新的文件夹 2.把需要归类的文件放入新建的文件中 3.右键然后选择add..... 4.运行此程序&#xff0c;会报错因为文件路径改变了&#xff0c;需要在.pro中修改路径 注意事项 文件夹内部…

Java中的JMX的使用

文章目录 1. 定义和存在的意义2. 架构2.1 Instrumentation2.2 JMX Agent2.3 Remote Management 3. 启动和连接3.1 注册MBean3.2 有两个方式启动JMX Agent3.3 Remote Management(客户端) 4. MBeanServerConnection使用4.1 列出所有的MBean4.2 列出所有的Domain4.3 MBean计数4.4 …

Windows + docker + python + vscode : 使用容器docker搭建python开发环境,无需本地安装python开发组件

下载docker for Windows docker window下载 如果没有翻墙工具&#xff0c;可以该网盘中的docker 链接&#xff1a;https://pan.baidu.com/s/11zLy3e5kusZR-4m_Fq_cqg?pwdesmv 提取码&#xff1a;esmv 安装docker docker的安装会重启电脑&#xff0c;不要惊讶&#xff0c;且…

音视频开发:音频fdk-aac编码

编码的大概流程见下图 1.获取编码器: avcodec_find_encoder_by_name("libfdk_aac") 2.检查PCM格式是否被编码器支持 3.创建编码上下文: AVCodecContext *ctx avcodec_alloc_context3(codec) 4.给上下文设置参数 5.打开编码器: avcodec_open2 6.创建AVFrame: a…

GPT-4 惨遭削弱;拼多多市值一度超阿里;雷军回应个人向武汉大学捐款 13 亿元丨 RTE 开发者日报 Vol.96

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有…

【VScode】超详细图片讲解下载安装、环境配置、编译执行、调试

这里是目录 VScode是什么&#xff1f;VScode的下载和安装环境介绍安装中文插件 配置VScodeC/C开发环境下载和配置MinGW-w64 编译器套件下载&#xff1a;配置&#xff1a; 安装C/C插件在VScode上编写代码设置C/C编译选项创建执行任务编译执行如果想写其他代码在同一个文件夹在不…

【性能测试】性能测试监控关键指标

系统指标 检测性能测试是否有bug的关键指标 1、系统指标——与用户场景及需求直接相关。 并发用户数&#xff1a;某一物理时刻同时向系统提交请求的用户数。平均响应时间&#xff1a;系统处理事务的响应时间的平均值&#xff0c;对于系统快速响应类页面&#xff0c;一般响应…

vue.js ——Vuex

基本概念 vue进行开发过程中有没有遇到这样一种场景&#xff0c;就是有些时候一些数据是一种通用的共享数据&#xff08;比如登录信息&#xff09;&#xff0c;那么这类数据在各个组件模块中可能都会用到&#xff0c;如果每个组件中都去后台重新获取那么势必会造成性能浪费&am…

Linux介绍

文章目录 前言一、概述 前言 Linux学习笔记。 一、概述 linux怎么读,不下10种 linux是一个开源、免费的操作系统&#xff0c;其稳定性、安全性、处理多并发已经得到业界的认可&#xff0c;目前很多企业级的项目(c/c/php/python/java/go)都会部署到Linux/unix系统上。 常见的…

每日一练2023.11.30——谁先倒【PTA】

题目链接&#xff1a;谁先倒 题目要求&#xff1a; 划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为&#xff1a;每人口中喊出一个数字&#xff0c;同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和&#xff0c;谁就输了&#xff0…

『OPEN3D』1.8.1 ICP配准

a目录 1、点到点&#xff08;point2point&#xff09;的配准 2、 点到面&#xff08;point2plane&#xff09;的配准 3、基于颜色的配准(color-icp) 4、点云配准核函数(robust kernel) 前面已经介绍过点云配准的基础理论内容&#xff0c;可以查看之前的文章&#xff1a; 『…

Unity Canvas、Canvas Scaler、Graphic Raycaster、EventSystem 组件详解

文章目录 0. 参考文章1. Canvas1.1 Screen Space-Overlay —— 屏幕空间覆盖模式1.2 Screen Space-Camera —— 相机模式1.3 World Space —— 世界模式 2. Canvas Scaler&#xff1a;控制UI画布的放大缩放的比例2.1 Constant Pixer Size —— 恒定像素2.2 Scale With Screen S…

98.套接字-Socket网络编程1(基础概念)

目录 1.局域网和广域网 2.IP 互联网协议(Internet Protocol) IP的作用 3.查看IP地址 Windows上查看IP ​编辑 Linux上查看IP 4.端口 主要类型&#xff1a; 用途&#xff1a; 示例&#xff1a; 端口的表示&#xff1a; 5.OSI/ISO 网络分层模型 1.局域网和广域网 …

2021年6月3日 Go生态洞察:Fuzzing技术的Beta测试

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…