标签:insert 输入 显示 来讲 deque 作用 nta 两种 splay
近日在看《STL源码解析》,STL里面一大堆泛型编程的确是非常巧妙,不过由于时间有限,我还是只能更加专注于日常使用比较多的一些知识。
Adapter是我在最开始使用STL Container的时候就听到的一个词,一直以来没有比较深入的了解,借着这次学习STL源码,在这里总结一下:
首先是Adapter的定义,《Design Patterns》中对于Adapter的定义我觉得真的十分准确:将一个Class的接口转换成另一个Class的接口,使原本因接口不兼容而不能合作的Class可以一起运作。这很直接就能让我想到日常生活中常见的Adapter:电源适配器。同样的,其实两者的作用也差不多。
STL里面主要有两种接配器(Adapter):容器接配器(Container Adapter)和迭代器接配器(Iterator Adapter),下面举几个例子了解一下这两类主要的Adapter:
Container Adapter:
最常用的容器接配器无非是queue和stack,从意义上来说,他们为底层的容器提供了一层包装,使得底层的容器只表现出这些接配器所定义的数据结构的功能。
这里假设底层容器是deque,双向开口,而且两端插入删除都能够实现O(1)的时间复杂的。当作为queue进行包装的时候deque就会封闭一端的插入操作,封闭另一端的删除操作,使得整个deque表现出FIFO的特性,在作为stack的时候同理。
可以看到Container Adapter做到的功能很直观,也很好理解,只是对于容器的一层包装,改变了数据结构的接口的同时方便了我们对其的理解和使用。
Iterator Adapter(#include<iterator>):
迭代器接配器是我原先并不是很熟悉的,对于STL中iterator的使用我可能最多的也就是begin(),end(),const_iterator,rbegin()等等,而在这里我要讲的Iterator Adapter主要有三种,分别是insert iterator,reverse iterator,iostream iterator。
首先是insert iterator。从定义上来讲,它的作用是将一般迭代器的赋值(assign)操作转变为插入(insert)操作。理解了这句话也就理解了insert iterator的本质。
下图显示的是STL里面insert iterator的主要用法:
这三种形式的最大区别无非就是使用Adapter之后元素插入的位置了。
先来一段最简单的测试代码:
1 #include<iostream> 2 #include<iterator> 3 #include<vector> 4 using namespace std; 5 6 int main(){ 7 vector<int> data={6,2,3,4,5,9}; 8 for(int i = 0;i<10;++i){ 9 *back_inserter(data)=i; 10 } 11 12 for(auto j:data) cout<<j<<" "; 13 cout<<endl; 14 return 0; 15 }
输出结果:6 2 3 4 5 9 0 1 2 3 4 5 6 7 8 9
可以看到,我们依然可以把经过Iterator Adapter修饰之后的结果当成是一种迭代器,依然可以用*符号,但不同的是当你对它进行赋值的时候,它将自动进行insert操作。使用原书中的描述应该更好:
也就是说在insert iterator的封装下,该iterator只是将assign操作变成了push_back,push_front,insert,而其他操作++,--,*全部返回原先的iterator
这也就能够解释copy函数的时候进行复制的底层实现了,在每复制一个值后的++对insert iterator并不起作用,只有赋值assign会起到相关操作。
当使用copy函数的时候:
1 #include<iostream> 2 #include<iterator> 3 #include<vector> 4 #include<algorithm> 5 using namespace std; 6 7 int main(){ 8 vector<int> data={6,2,3,4,5,9}; 9 vector<int> res={2,1,1}; 10 copy(data.begin(),data.end(),back_inserter(res)); 11 for(auto j:res) cout<<j<<" "; 12 cout<<endl; 13 return 0; 14 }
输出结果:2 1 1 6 2 3 4 5 9
copy的时候每次都是从res的末尾插入一个数字并进行copy,而不像copy本义中只存在的赋值而已。
reverse iterator:
显然作用是使得iterator方向相反,常和rbegin,rend一起使用,比如:
1 #include<iostream> 2 #include<iterator> 3 #include<vector> 4 #include<algorithm> 5 using namespace std; 6 7 int main(){ 8 vector<int> data={6,2,3,4,5,9}; 9 vector<int>::reverse_iterator it = data.rbegin(); 10 for(;it!=data.rend();++it) cout<<*it; 11 cout<<endl; 12 return 0; 13 }
输出:954326
iostream iterator:
这种Adapter将iterator和输入输出流(可以是文件流)相关联,经常和copy函数联合使用:
1 #include <iostream> // std::cout 2 #include <iterator> // std::ostream_iterator 3 #include <vector> // std::vector 4 #include <algorithm> // std::copy 5 6 int main () { 7 std::vector<int> myvector; 8 for (int i=1; i<10; ++i) myvector.push_back(i*10); 9 10 std::ostream_iterator<int> out_it (std::cout,", "); 11 std::copy ( myvector.begin(), myvector.end(), out_it ); 12 return 0; 13 }
输出:10, 20, 30, 40, 50, 60, 70, 80, 90,
从上面的例子中可以看到,接配器(Adapter)在STL中有着重要作用,其和copy等常用函数关系紧密,同样可以和输入输出等操作进行结合。
参考:《STL源码剖析》
http://www.cplusplus.com/reference/iterator/ostream_iterator/
标签:insert 输入 显示 来讲 deque 作用 nta 两种 splay
原文地址:https://www.cnblogs.com/J1ac/p/9025175.html