1. 使用迭代器的原因

  下面用两个遍历函数引出使用迭代器的原因。实现细节上来看,两个 find 函数算法不同,但广义上来看,他们的目的都是匹配值相同的一项。

// 给定一个double数组, 返回值相同的一项
double* find_ar(double* ar, int n, const double & val){
for(int i=0; i<n; i++)
if(ar[i] == val)
return &ar[i];
return 0;
}
// 给定一个链表节点, 返回值相同的一项
Node* find_ll(Node* head, const double& val){
Node* start;
for(start = head; start!=0; start = start->p_next)
if(start->item == val)
return start;
return 0;
}
  • 迭代器要求:为不同的类设计迭代器,并为迭代器定义p++、++p、p=q
  • 容器要求:让数组和链表拥有超尾元素,迭代器到达超尾元素后结束搜索
typedef double* iterator;
iterator find_ar(iterator ar, int n, const double& val){
for(int i=0; i<n; i++, ar++)
if(*ar == val)
return ar;
return 0;
}
iterator find_ar(iterator begin, iterator end, const double& val){
iterator ar;
for(ar=begin; ar != end; ar++)
if(*ar == val)
return ar;
return end; // 未找到
}

2. 迭代器类型

  不同算法对迭代器的要求不同。查找算法只需要读取数据;而排序算法需要读写数据和随机访问,例如 iter 是一个迭代器,需要重新定义 + 运算符来实现 iter + 10 访问元素

  • 输入迭代器:输入是从程序的角度来说的,迭代器向程序输入,因此需要迭代器可以解引用使程序能读取迭代器中的值,但不需要修改迭代器中的值。注意迭代器是单项迭代器,只能递增不能递减,迭代器递增后也不能保证先前的值仍可以被解引用。
  • 输出迭代器:输出是从程序输出到迭代器,因此需要迭代器可以被写入。注意输出迭代器只能写入却不能读取,这就类似于 cout 可以向屏幕输出但不能读取屏幕内容。
  • 正向迭代器:正向迭代器与输入和输出迭代器相同,只能使用++运算符遍历容器。但正向迭代器递增后,仍然可以对前面迭代器的值解引用,并且支持输入和输出
  • 双向迭代器:同时支持++和--
  • 随机访问迭代器:允许从一个元素直接跳到另一个元素称为随机访问,它具有双向迭代器的所有特性

3. 迭代器层次结构

3.1 将指针用作迭代器

  迭代器是广义指针,而指针满足迭代器的所有要求。迭代器是STL算法的接口,而指针就是迭代器,因此STL算法可以直接使用最普通的指针来进行一些操作,下面给出一个例子

const int SIZE = 100;
double Receipts[size];

  STL sort() 函数接收容器第一个指针和超尾指针作为参数,即&Receipts[0] 和 &Receipts[SIZE],也可以是下面的写法。因为c++将超尾概念用于数组,所以我们可以将STL算法用于常规数组

sort(Receipts, Receipts + SIZE);

4. 容器类型

4.1 序列容器

4.1.1 vector

  vector 是数组的一种类表示,它提供了自动内存管理功能,容量随着元素添加和删除而增大和缩小。vector 是可翻转容器(reversible container),rbegin() 和 rend() 返回的是反转后的第一个元素的迭代器和反转后的超尾迭代器

for_each(dice.begin(), dice.end(), Show);    // 顺序显示
for_each(dice.rbegin(), dice.rend(), Show(); // 逆序显示

4.1.2 deque

  deque 是双端队列,实现类似于 vector 容器,支持随机访问。与 vector 的主要区别是它在队列开始位置的插入和删除时间是固定的,而非线性

4.1.3 list和forward_list(C++11)

  list 是双向链表,C++11 中实现了单链表 forward_list

4.1.4 queue和priority_queue

  queue 是一个适配器类,实现了队列的功能(先进先出),底层实现默认为 deque

  priority_queue是另一个适配器类,支持的操作与queue相同,但它自动将最大的元素移动到队首,默认底层类为 vector

4.1.5 stack

  stack 是一个适配器类,默认底层类为vector,实现了栈的功能(后进先出)

4.1.6 array(C++11)

  array不是STL容器,因为它的长度是固定的,但它定义了 operator[] () 和 at(),许多STL算法适用于array

4.2 关联容器

4.2.1 set和multiset

  set 是关联集合,可以反转和自动排序,且键是唯一的,默认情况下使用模板less<>来对键进行排序

set<string> A;
set<string, less<string>> A; // 这是完整写法

  排序方法决定了插入的位置,所以只需要提供插入的信息即可

int main(){
const int N = 6;
string s1[N] = { "buffoon", "thinkers", "for", "heavy", "can", "for" };
set<string> A(s1, s1 + N); // 利用容器的构造方法, 给定了第一个元素的指针和超尾指针
ostream_iterator<string, char> out(cout, " ");
copy(A.begin(), A.end(), out); // buffoon can for heavy thinkers
}

4.2.2 map和mutimap

  map和set最大的区别是,map的键和值类型不同,默认情况下也使用less进行排序

map<int, string> code;
map<int, string, less<int>> code;

  下面是一个mutimap的例子,codes.equal_range(213) 返回一个键值对,包含两个迭代器,包含了键为213的所有值的信息,可以通过遍历这个迭代器得到

int main(){
multimap<int, string> codes;
pair<const int, string> item(213, "Los Angeles");    // 创建一个键值对
codes.insert(item);   // 插入元素
codes.insert(pair<const int, string>(213, "Los Angeles"));   // 插入元素
codes.insert(pair<const int, string>(213, "Los Angeles 2")); // 插入元素
codes.insert(pair<const int, string>(213, "Los Angeles 3")); // 插入元素
pair<multimap<int, string>::iterator, multimap<int, string>::iterator> range
= codes.equal_range(213);
for (auto it = range.first; it != range.second; ++it)
{
cout << (*it).second << endl;
}
}

4.3 无序关联容器

无序关联容器与关联容器相同,将值和键关联起来,但关联容器底层通过树实现,无序关联容器通过哈希表实现,目的是提高添加和删除元素的速度以及查找算法的效率,它们是unordered_set、unordered_multiset、unordered_map、unordered_multimap

【C++ Primer Plus】泛型编程之迭代器和容器的更多相关文章

  1. C++ Primer 阅读笔记:迭代器和容器 小结

    原创 by zoe.zhang  0.写在前面的话 我是在2011年学的C++,但是那一年恰好是C++11新标准的一年,但是大学上学的C++还是基于C++98的风格的,使用的编译器也是VC6.0,啊, ...

  2. Java并发(五):并发,迭代器和容器

    在随后的博文中我会继续分析并发包源码,在这里,得分别谈谈容器类和迭代器及其源码,虽然很突兀,但我认为这对于学习Java并发很重要; ConcurrentModificationException: J ...

  3. C++进阶 STL(1) 第一天 [容器,算法,迭代器] string容器 vector容器 deque容器

    课程大纲 02实现基本原理 容器,算法,迭代器 教室:容器 人:元素 教室对于楼:容器 序列式容器: 容器元素在容器中的位置是由进入容器的时间和地点来决定 序列式容器 关联式容器: 教室中 按年龄排座 ...

  4. C++ Primer 5th 第11章 关联容器

    练习11.1:描述map 和 vector 的不同. map是关联容器,vector是顺序容器,关联容器与值无关,vector则与值密切相关 练习11.2:分别给出最适合使用 list.vector. ...

  5. C++ Primer 5th 第9章 顺序容器

    练习9.1:对于下面的程序任务,vector.deque和list哪种容器最为适合?解释你的选择的理由.如果没有哪一种容器优于其他容器,也请解释理由.(a) 读取固定数量的单词,将它们按字典序插入到容 ...

  6. 【C++】:STL迭代器使用---[容器::iterator iter;]

    参考文章:http://blog.csdn.net/qq_23100787/article/details/51388163 迭代器这种东西,就是为了使访问简单!! 容器::iterator iter ...

  7. 56 容器(十)——Iterator迭代器遍历容器

    迭代器的获取 LIst与Set容器统一使用他们的对象.Iterator()方法获得迭代器对象,然后使用while循环配合迭代器的方法hasNext()及next()来遍历容器. List<Str ...

  8. 把《c++ primer》读薄(3-2 标准库vector容器+迭代器初探)

    督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 标准库vector类型初探,同一种类型的对象的集合(类似数组),是一个类模版而不是数据类型,学名容器,负责管理 和 存储的元素 ...

  9. C++ Primer : 第九章 : 顺序容器的定义、迭代器以及赋值与swap

    顺序容器属于C++ STL的一部分,也是非常重要的一部分. 顺序容器包括: std::vector,包含在头文件<vector>中 std::string, 包含在头文件<strin ...

  10. C++_系列自学课程_第_5_课_vector容器_《C++ Primer 第四版》

    再一次遇到 vector 这个单词; 每一次见到这个单词都感觉这个单词非常的 "高大上"; 数字遇到vector马上就可以360度旋转: 当 "电" 遇到vec ...

随机推荐

  1. Java 自定义线程池的任务

      在<Java 自定义线程池的线程工厂>一文中介绍了如何优雅地自定义线程工厂,本文介绍如何自定义线程池的任务,并拿到返回值.   首先自定义一个任务类,实现Callable接口,重写ca ...

  2. linux安全基线自查手册

    1.Redhat/CentOS 7.x配置模板 1.1 帐号管理 1.1.1 检查是否设置除root之外UID为0的用户 严重级别:中危 理论依据:任何UID为0的帐户都具有系统上的超级用户特权,只有 ...

  3. 破局AI问答专有名词检索迷局:分词期神器强势登场!

    有客户深度使用全文检索模式检索分段,反馈一些专有名词无法被检索到(例如把"小米手机"分成了"小米"和"手机"两个词,对检索结果造成较大干扰) ...

  4. 【实战】基于 Tauri 和 Rust 实现基于无头浏览器的高可用网页抓取

    一.背景 在 Saga Reader 的早期版本中,存在对网页内容抓取成功率不高的问题.主要原因是先前采用的方案为后台进程通过 reqwest 直接发起 GET 请求获取网站 HTML 的方案,虽然仿 ...

  5. HarmonyOS Next快速入门:为什么学习HarmonyOS NEXT?

    鸿蒙基础知识##HarmonyOS Next快速入门## 点击跳转<HarmonyOS Next快速入门>视频教程 学习HarmonyOS NEXT的原因主要有以下几点: 一.技术前沿与创 ...

  6. Hi,我是ChunJun,一个有趣好用的开源项目

    Hi,我是ChunJun,一个有趣好用的开源项目. 今天我们正式开通了自己的公众号!欢迎大家关注~ 数字经济时代,各行各业数字化转型大趋势下,数据要素成为关键.海量多源异构数据汇聚,使得数据同步面临同 ...

  7. hot100之贪心

    买卖股票的最佳时期(121) class Solution { public int maxProfit(int[] prices) { int res = 0; int min = Integer. ...

  8. Java 开发者无痛迁移到 Cursor 开启AI编程新生涯

    习惯了IntelliJ IDEA的Java开发者,想尝试Cursor.Windsurf或Trae这类新兴的AI IDE,却担心迁移成本? 本文分享我的实战经验,帮助你高效切换开发环境,保留核心效率.效 ...

  9. ChatGPT学习之旅 (6) 聊聊AI人设

    大家好,我是Edison. 上一篇:Prompt终极用法 通过前面5篇内容我们了解了从基础到高级的Prompt用法,今天我们来聊聊AI的人设! 打造人设的步骤:只要3步 在Prompt实践中,我们了解 ...

  10. MySQL——InnoDB存储引擎

    .ibd文件结构 从 MySQL 5.6.6 版本开始,默认一个表是一个.ibd文件,关于表的所有信息都保存在这个文件里.数据库IO操作的基本单位是页,.idb的基本组成也是页,如下图所示,一个.id ...