趣乐博思剑指信奥 C++ 系列

趣乐博思剑指信奥系列,专门针对全国青少年信息学奥林匹克联赛 NOIP 而开展的专业教育方案。开设的课程有 C 语言基础,C++ 语言基础,算法设计入门与进阶,经典试题分析与详解等系列课程。面向10 - 16 岁少儿的编程教育,培养扎实的 C++ 语言基础,灵活运用算法的能力,分析解决问题的能力。

剑指信奥 | C++ 之 STL - 迭代器(上)

各个容器统一的访问接口

什么是迭代器

还记得我们在介绍 C++ STL 的概念时,提到了 STL 包含四个组件吗?

它们分别是 容器迭代器算法函数,到目前为止,我们关于容器部分的内容已经基本结束了,它们分别是:

  • string
  • vector
  • stack
  • queue
  • list
  • set
  • map

这些容器的主要作用就是用来存储数据,依据它们底层不同的数据结构,存储的方式也各不相同,因此带来增查改删各种操作时间和空间上的差异,人们在使用时就可以根据具体的需求做出最佳的选择。

虽然都是不同的容器,但从这几次课的学习,我们不难发现,我们对容器的很多操作都是类似的,比如在容器中查找一个特定的元素,查找满足需求的一部分元素,修改元素等等。

如果为每一种容器都重新定义一套函数,实在是麻烦而且没有必要,如果能有一个统一的方式能对所有的容器提供访问功能就好了,而这,就是我们今天要学习的内容 — 迭代器 iterator

迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式。

迭代器是可在容器(container,例如链表或阵列)上遍历的接口,设计人员无需关心容器内存分配的实现细节。

Wikipedia

所以,迭代器就是访问容器的统一接口。

一个迭代器的示例

在开始介绍迭代器的具体内容之前,我们先来看一个迭代器使用的实例:

#include #include 

using namespace std;

int main() {

// 容器的初始化vector<int> container{1, 2, 3};

// 迭代器的定义vector<int>::const_iterator i;

// for 循环 1cout << "--- for 1 ---" << endl;for (i = container.begin(); i != container.end(); i++) {cout << *i << "\t";    }

// for 循环 2cout << endl << "--- for 2 ---" << endl;for (i = container.begin(); i < container.end(); i++) {cout << *i << "\t";    }

// while 循环cout << endl << "--- while ---" << endl;    i = container.begin();while (i != container.end()) {cout << *i << "\t";        i++;    }

return 0;}

/* output:    --- for 1 ---    1 2   3    --- for 2 ---    1 2   3    --- while ---    1 2   3 */

在这段代码中,我们先是初始化了一个具有 3 个元素的向量,然后使用 vector::iterator = i; 的方式声明了一个关于这个容器的迭代器 i

之后,以两种 for 循环和一个 while 循环的方式输出了这个容器的所有元素,三次遍历的输出结果都是一样的。

现在,我们改动上述代码中的 3 行,仔细观察一下是在哪里:

#include #include 

using namespace std;

int main() {

// 容器的初始化deque<int> container{1, 2, 3};

// 迭代器的定义deque<int>::const_iterator i;

// for 循环 1cout << "--- for 1 ---" << endl;for (i = container.begin(); i != container.end(); i++) {cout << *i << "\t";    }

// for 循环 2cout << endl << "--- for 2 ---" << endl;for (i = container.begin(); i < container.end(); i++) {cout << *i << "\t";    }

// while 循环cout << endl << "--- while ---" << endl;    i = container.begin();while (i != container.end()) {cout << *i << "\t";        i++;    }

return 0;}

/* output:    --- for 1 ---    1    2   3       --- for 2 ---    1  2   3       --- while ---    1  2   3    */

找到了吗?是这样的 3 行:

  1. #include 改为 #include
  2. vector container{(1, 2, 3}; 改为 deque container{1, 2, 3};
  3. vector::const_iterator i; 改为 deque::const_iterator i;

简单一点说,我们是把容器由向量 vector 改为了双端队列 deque,三处循环代码没有任何改变,同样实现了容器的遍历。

这就体现了迭代器的作用:为容器提供统一的访问接口。

迭代器的定义分类

迭代器是有分类的,我们先看一段代码:

#include #include 

using namespace std;

int main() {

// 容器的初始化vector<int> container{1, 2, 3};

// 迭代器的定义vector<int>::iterator i; // 正向迭代器

// for 循环 1cout << "--- for 1 ---" << endl;for (i = container.begin(); i != container.end(); i++) {        *i += 1; // 修改元素的值    }

// for 循环 2cout << endl << "--- for 2 ---" << endl;for (i = container.begin(); i < container.end(); i++) {cout << *i << "\t";    }

return 0;}

/* output:    --- for 1 ---    --- for 2 ---    2    3   4    */

这段代码和之前第一个代码片段很像,不同在以下两行:

  1. vector::const_iterator i; 改为 vector::iterator i;
  2. cout << *i << "\t"; 改为 *i += 1;

首先,我们修改了迭代器的类型。

我们把 const_iterator 改为 iterator。

其次,在第一个 for 循环中,把输出语句改为了赋值语句。

这里 const_iterator常量正向迭代器 的含义,它只能实现元素的访问,不能修改元素,而 iterator正向迭代器 的含义,它不仅能实现元素的访问,还可以修改元素的值。

所以,迭代器按照定义方式分为以下四类:

1. 正向迭代器,定义方法如下:

容器类名::iterator 迭代器名;

2. 常量正向迭代器,定义方法如下:

容器类名::const_iterator 迭代器名;

3. 反向迭代器,定义方法如下:

容器类名::reverse_iterator 迭代器名;

4. 常量反向迭代器,定义方法如下:

容器类名::const_reverse_iterator 迭代器名;

我们知道了,各种迭代器都可以访问元素,而非常量迭代器还可以修改元素,那么正向迭代器和反向迭代器有什么区别呢?

今天课程的最后,我们看一个反向迭代器的示例:

#include #include 

using namespace std;

int main() {

vector<int> container{1, 2, 3};

// 迭代器的定义vector<int>::reverse_iterator i; // 反向迭代器

// for 循环 1cout << "--- for 1 ---" << endl;for (i = container.rbegin(); i != container.rend(); i++) {cout << *i << "\t";        *i *= 2; // 修改元素的值    }

// for 循环 2cout << endl << "--- for 2 ---" << endl;for (i = container.rbegin(); i < container.rend(); i++) {cout << *i << "\t";    }

return 0;}

/* output:    --- for 1 ---    3  2   1       --- for 2 ---    6  4   2    */

我们这次定义了一个非常量反向迭代器,在 for 循环 1 中,首先输出元素,紧接着修改了每个元素值为原来的 2 倍,再次使用 for 循环 2 输出修改后的值。

输出结果表明,元素是逆序输出的,体现了反向的含义,需要注意的是,反向迭代器的两端使用的是 rbegin()rend() 函数,而循环里的 ++ 将指向容器里的前一个元素。

关于迭代器第一部分的内容,我们就说到这,下次课我们继续聊聊迭代器后续的内容。


「 剑指信奥 C++ 系列 

从零开始,进阶信息学奥林匹克竞赛

清华计算机系哥哥专业讲解


趣乐博思教育

遇见你更优秀的孩子

‏r

如果您喜欢 趣乐博思教育,请关注我们的公众号,发现您更优秀的孩子!

如果您从这篇文章有所收获,请点亮下方 在看,或转发到朋友圈,谢谢!

stl clocklist 查找元素_剑指信奥 C++ 之 STL 迭代器(上)相关推荐

  1. c语言一维数组逆序输出_剑指信奥 | C 语言之兵人来袭!

    趣乐博思剑指信奥系列 ❝ 趣乐博思剑指信奥系列,专门针对全国青少年信息学奥林匹克联赛 NOIP 而开展的专业教育方案.开设的课程有 C 语言基础,C++ 语言基础,算法设计入门与进阶,经典试题分析与详 ...

  2. c语言 read 文件字节没超过数组大小时会怎样_剑指信奥 | C 语言之信奥试题详解(四)...

    趣乐博思剑指信奥系列 ❝ 趣乐博思剑指信奥系列,专门针对全国青少年信息学奥林匹克联赛 NOIP 而开展的专业教育方案.开设的课程有 C 语言基础,C++ 语言基础,算法设计入门与进阶,经典试题分析与详 ...

  3. stl clocklist 查找元素_C++算法竞赛中常用的STL

    什么是STL? STL,Standard Template Library的缩写,标准模版库的意思.STL是一些"容器"的集合,这些容器包括list. vector.set.que ...

  4. 在数组中查找指定元素_剑指 offer 第一题: 二维数组中的查找

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  5. stl clocklist 查找元素_C++|通俗理解STL

    "存储程序"是电子计算机技术一个很重要的概念.程序能在计算机上运行,必须先让程序代码从其他的一些存储介质(如光盘或硬盘)读入到内存,然后才能由控制器从内存读取.解释并产生控制信号, ...

  6. leetcode 打印_剑指 Offer 总结 - leetcode 剑指offer系列

    剑指 Offer 系列完结撒花!! 本篇文章是对整个系列的精华总结, 对系列的每篇文章进行了分类, 并用一句话概括每道题的思路, 方便大家理解和记忆, 当然也包含原文完整链接供大家参考 总的来说, 写 ...

  7. 数组中重复的元素(剑指Offe.03)

    数组中重复的元素(剑指Offe.03) 题目描述: 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了 ...

  8. 字符串全排列算法_C#版_剑指OFFER

    字符串全排列算法_C#版_剑指OFFER 题目描述 ​题目描述 输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组. 例如输入字符串ABC,则输出由字符A, ...

  9. 剑指offer——面试题23:从上往下打印二叉树

    剑指offer--面试题23:从上往下打印二叉树 Solution1: 典型的BFS算法! 思路一开始没想到,按照书上的思路写的答案... 注意:deque是双向队列,在头尾插入都很快! /* str ...

最新文章

  1. Android多线程分析之二:Thread的实现
  2. 线程中发送消息阻塞问题解决
  3. 【学习笔记】《Go 指南》
  4. 4.2串的表示和实现
  5. 【雷达通信】基于matlab CDIF算法雷达信号分选【含Matlab源码 1186期】
  6. 联想笔记本键盘亮屏幕不亮_联想笔记本电脑开机键亮但是黑屏?键盘没反应?
  7. 关于Android直接连MySQL获取数据的真机测试的一些坑
  8. 计算机网络原理——传输层TCP协议的十个重要特性之保证可靠性的机制(确认应答和超时重传)
  9. 如何关闭/屏蔽百度搜索结果的置顶广告?(无耻的百度关了又自己开启)
  10. 去除枕头异味的两种方法
  11. 为什么qq不出linux版本,腾讯QQ官方Linux版本要发布了
  12. Java在手机平台上的Porting
  13. 快速开发小程序——案例
  14. MFC连接SQL数据库操作
  15. SpringBoot(5)响应式编程WebFlux
  16. ubuntu提示系统缺失字体:symbol、wingdings、wingdings2、wingdings3、webdings,WPS无法正确显示...
  17. -17的计算机编码,大众电脑编码大全
  18. live server
  19. BoomBoomBoom
  20. yocto 安装toolchain

热门文章

  1. NFS mount failed, reason given by server: Permission denied ---nfs挂载失败
  2. 有小数点是什么类型_为什么0.1+0.2不等于0.3?原来编程语言是这么算的……
  3. Traveling on the Axis (The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online)
  4. 5.1.2 操作系统控制I/O设备的I/O控制器
  5. 2013 JavaB2 马虎的算式
  6. 帝国cms怎么增加php,帝国CMS增加系统配置字段
  7. 设计模式的理解:命令模式 (Command)
  8. Linux / sudo、su、sudo su、sudo -i 使用和区别
  9. python子进程关闭fd_如果创建了multiprocessing.Pool,Python子进程wait()将失败
  10. sql server windows nt cpu占用高_痛惜!年仅33岁著名球员患癌去世!曾是高以翔扮演角色原型...