博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ Primer Plus 学习笔记 第十六章 泛型编程 迭代器,容器
阅读量:4127 次
发布时间:2019-05-25

本文共 4977 字,大约阅读时间需要 16 分钟。

迭代器的意义

迭代器应该有的特征

前i++和++i的操作符重写

建议

stl总结

STL的五种迭代器类型

1.输入迭代器(读取容器中的数据) 

不修改容器中的值

上图说的情况可能是指类似链表一样的数据结构的迭代

2.输出迭代器(修改容器内的值,不读取)

3.正向迭代器

 输入迭代器 + 输出迭代器

只能往前走( + )不能回头看( - )

4.双向迭代器

正向迭代器+ 可以回头看 

5.随机访问迭代器

双向迭代器+ 随机访问

5个迭代器的层次结构

i为迭代器,n为整数

根据不同场景需求使用不同的迭代器,尽量使用要求最低的迭代器

STL的copy()默认不支持将数据copy到空对象中 

概念

模型

指针其实就是一个随机访问迭代器模型

 

STL提供的预定义迭代器

1. ostream_iterator模板

适配器。 输出迭代器

将一些其他接口转换为STL使用的接口

 

2.istream_iterator模板

输入迭代器

跟ostream_iterator相反

 

其他的预定义迭代器类型

reverse_iterator

用来反向迭代

这里涉及到两个成员函数(vector类)

rbegin()和rend() 

rbegin() 指向超尾的反向迭代器

rend() 指向第一个元素的反向迭代器

当使用rbegin()时不能解引用 因为是指向超威。 所以必须要往前走一个位置

rend()是在第一个位置。所以要提前一个位 因为 区间的结尾处不包括在区间中。

程序示例

#include 
#include
#include
#include
int main(){ using namespace std; int casts[10] = {6, 7, 2, 9, 4, 11, 8, 7, 10, 5}; vector
dice(10); copy(casts, casts + 10, dice.begin()); cout <<"Let the dice be cast.\n"; ostream_iterator
out_iter(cout, " "); copy(dice.begin(), dice.end(), out_iter); cout << endl; return 0;}

运行结果

尽量使用STL函数来处理内部问题

这是复制到out_iter中

这样有两个问题 第一个是 要事先有固定长度,并且会覆盖掉原来的内容。

另外三种迭代器解决了这两个问题 

back_insert_iterator, front_insert_iterator insert_iterator

使用方法:

将容器作为模板参数传入

front_insert_iterator和 back_insert_iterator

back_insert_iterator<vector<int>> back_iter(dice);

 

insert_iterator

insert_iterator必须要添加一个插入位置的构造函数参数

insert_iterator<vector<int>> insert_iter(dice, dice.begin())

程序示例

#include 
#include
#include
#include
#include
void output(const std::string & s) {std::cout << s << " ";}int main(){ using namespace std; string s1[4] = {"fine", "fish", "fashion", "fate"}; string s2[2] = {"busy", "bats"}; string s3[2] = {"silly", "singers"}; vector
words(4); copy(s1, s1 + 4, words.begin()); for_each(words.begin(), words.end(), output); cout << endl; copy(s2, s2 + 2, back_insert_iterator
>(words)); for_each(words.begin(), words.end(), output); cout <
> (words, words.begin())); for_each(words.begin(), words.end(), output); cout << endl; return 0;}

程序说明

 

容器种类

15种 嗯。。很多

容器概念

容器的实现没有继承 所以在理论上描述其通用特征 以便所有的容器遵循这些特征

概念1,容器中存储对象的要求

c++11增加了可复制插入和可移动插入

基本的容器特征要求

X:容器类型

T: 存储在容器中的对象类型

a,b:类型为X的值

r:X&的值

u:类型为X的标识符

复杂度:表示事件复杂到 从快到慢为:编译时间->固定时间->线性时间

就是算法的时间复杂度

C++ 11新加的对容器的要求

rv:X的非常量右值,如函数的返回值

嗯。。。18章再说

 

序列:

基本容器的改进(类似继承)

7种STL容器: deque, forward_list, list, queue, priority_queue, stack, vector

array也算,但并不满足所有的序列所有的要求

序列的要求

X:容器类型

T: 存储在容器中的对象类型

a,b:类型为X的值

r:X&的值

u:类型为X的标识符

t:表示类型为T的值

n:整数

p,q,i,j:迭代器

序列可选的要求

a.at(t) 会检查边界,超出的话会抛out_of_range异常

push_front(t)和pop_front(t)中不包含vector的原因 如果让vector也有该功能的话 那时间复杂度是线性的

各序列容器说明

vector:

动态分配内存,自动内存管理。提供对元素的四季访问。

在尾部添加和删除:固定时间

头部、中间插入或删除元素:线性时间

也是反转容器 rbegin(), rend()

2.deque:

双端队列

vector + 开头位置的插入和删除的时间复杂度是固定的。

处理速度比vector慢

3.list:

双向链表

vector + 任意位置插入和删除的时间复杂度是固定的。

vector强调的是通过随机访问进行快速访问

list签掉的是快速插入和删除

(这其实就是线性表和链表的差别)

也是可翻转容器

不支持数组表示和随机访问

list独有的成员函数

list程序示例:

#include 
#include
#include
#include
void outint(int n) {std::cout << n << " ";}int main(){ using namespace std;// 建立元素为5个2的list容器one list
one(5, 2); int stuff[5] = {1, 2, 4, 8, 6}; list
two;// 将stuff[0]到stuff[5]之间的元素拉到two头位置插入 two.insert(two.begin(), stuff, stuff + 5); int more[6] = {6, 4, 2, 4, 6, 5}; list
three(two); three.insert(three.end(), more, more + 6); cout << "List one: "; for_each(one.begin(), one.end(), outint); cout << endl << "List two: "; for_each(two.begin(), two.end(), outint); cout << endl << "List three: "; for_each(three.begin(), three.end(), outint);// 删除值为2的元素 three.remove(2); cout << endl << "List three minus 2s: "; for_each(three.begin(), three.end(), outint);// 将one的元素追加到three的头位置,one清空 three.splice(three.begin(), one); cout << endl << "List three after splice: "; for_each(three.begin(), three.end(), outint); cout << endl << "List one: "; for_each(one.begin(), one.end(), outint);// 删除three容器中连续相同的元素,注意 是连续相同 three.unique(); cout << endl << "List three after unique: "; for_each(three.begin(), three.end(), outint);// 排序 three.sort(); three.unique(); cout << endl << "List three after sort & unique: "; for_each(three.begin(), three.end(), outint); two.sort();// 合并 合并前需要先排序,才能合并,合并完two清空 three.merge(two); cout << endl << "Sorted two merged into three: "; for_each(three.begin(), three.end(), outint); cout << endl; cout << endl << "List two: "; for_each(two.begin(), two.end(), outint); cout << endl; return 0;}

运行结果

insert()是复制 splice()是移动

非成员sort()函数需要随机访问迭代器。但是list并不是 快速插入的代价是放弃随机访问功能。所以只能用成员函数版本的sort()

 

forward_list(C++ 11)

单链表 正向迭代器 

比list更简单,紧凑,功能更少

4.queue

头文件<queue>

ostream_iterator的适配器类,让输出流能够使用迭代器接口

底层是deque

不让随机访问,不让遍历, 

+队尾,-队首,看队尾和队首的值,元素数目,队列是否为空

5.priority_queue

<queue>

适配器。与queue区别在于 最大的元素放在队首 底层是vector

6.stack

<stack>

提供了栈接口

对栈的操作

7.array

<array>非STL

长度固定

参考第四章

没有定义调整容器大小的操作

有遍历的操作。 

可以使用copy()和for_each()等STL算法

先完结。 其他的明天再写 

 

转载地址:http://qiepi.baihongyu.com/

你可能感兴趣的文章
PHP中的stdClass 【转】
查看>>
XHProf-php轻量级的性能分析工具
查看>>
OpenCV gpu模块样例注释:video_reader.cpp
查看>>
就在昨天,全球 42 亿 IPv4 地址宣告耗尽!
查看>>
如果你还不了解 RTC,那我强烈建议你看看这个!
查看>>
Mysql复制表以及复制数据库
查看>>
Linux下SVN客户端使用教程
查看>>
Linux分区方案
查看>>
如何使用 systemd 中的定时器
查看>>
git命令速查表
查看>>
linux进程监控和自动重启的简单实现
查看>>
OpenFeign学习(三):OpenFeign配置生成代理对象
查看>>
OpenFeign学习(四):OpenFeign的方法同步请求执行
查看>>
OpenFeign学习(五):OpenFeign请求结果处理及重试控制
查看>>
OpenFeign学习(六):OpenFign进行表单提交参数或传输文件
查看>>
Ribbon 学习(二):Spring Cloud Ribbon 加载配置原理
查看>>
Ribbon 学习(三):RestTemplate 请求负载流程解析
查看>>
深入理解HashMap
查看>>
XML生成(一):DOM生成XML
查看>>
XML生成(三):JDOM生成
查看>>