• ###STL学习--迭代器


    点击查看Evernote原文

    #@author:       gr
    #@date:         2014-08-23
    #@email:        forgerui@gmail.com
    

    STL中的迭代器。

    ###stl学习
     |--迭代器
     |--类属算法
     |--容器
       |--vector
       |--deque
       |--list
       |--set
       |--map
     |--函数对象
     |--适配器
     |--分配器

    一、Contents

    1. 输入迭代器

    InputIterator要求:

    • 可以++
    • 可以==
    • 可以cout<<*it;取值

    可以看出,输入迭代器不是指某种类型,而是一系列类型,只要满足上面要求的迭代器都是输入迭代器。
    有一种迭代器可以从输入流中读取数据, 称为输入流迭代器。程序不断读取cin输入流,直到找到'x'或者为空时结束。

    //使用istream_iterator需要引入#include <iterator>
    istream_iterator<char> in(cin);
    istream_iterator<char> eos;
    find(in, eos, 'x');
    

    2. 输出迭代器

    OutputItertor要求:

    • 可以++
    • 可以*it = a;进行赋值, 但无法保证*it可以获取到其值

    输出迭代器不一定要满足==的条件。

    //输出流迭代器是特殊的输出迭代器
    ostream_iterator<string> out(ofstream("a.txt")); 
    

    3. 前向迭代器

    前向迭代器既是输入迭代器又是输出迭代器,所以既可以读数据又可以写数据,并且可以对序列时行单方向的遍历。
    可以保存一个前向迭代器,并利用它从同一个位置重新遍历,这样可以实现多次遍历,这使得前向迭代器不仅可以适应单遍扫描算法,还可以适应多遍扫描算法

    4. 双向迭代器

    既可以进行前向遍历,也可以进行反向遍历。这种双向遍历的能力在一些算法中至关重要,比如:reverse就需要双向迭代器。
    数组的内置指针类型满足这种情况。容器list(链表)也要提供双向迭代器。

    int a[] = (3, 5, 1, 4, 7);
    reverse(&a[0], &a[5]);
    list<int> l(&a[0], &a[5]);
    reverse(l.begin(), l.end());
    

    5. 随机访问迭代器

    这种迭代器更加灵活。可以在序列的任意两个位置进行跳转,这种操作的时间复杂度是常量。

    需要随机访问器的算法,如binary_search,利用序列的升序性,算法时间复杂度为O(log N),其中N为序列长度。而find的时间复杂度为O(N)。
    再比如sort算法需要随机访问迭代器,而list无法随机访问,所以sort不适应于list,可以调用list的成员函数。
    数组和vector(向量)和deque(双端队列)都是可以随机访问。

    6. 插入迭代器

    将类属算法转入到“插入模式”,而不是“改写模式”。即表达式*i = ...不再是使位置i处的对象被改写,而是在这个位置进行插入操作,且这个操作是通过容器的成员函数实现的。当输入流或一个容器向另一个容器传递数据时,这种插入操作特别有用。
    STL提供3种插入迭代器:

    back_insert_iterator<Container>   //使用push_back成员函数
    front_inert_iterator<Container>   //使用push_front成员函数
    inert_iterator<Container>         //使用insert成员函数
    

    下面看个例子:

    vector<int> vector1;
    deque<int> deque1(100, 1);
    //下面的代码将报错,vector1没有存储空间
    copy(deque1.begin(), deque1.end(), vector1.begin());
    

    上面的copy执行到*(vector1.begin()) = *(deque1.begin())时将报错,但如果使用插入迭代器作为第3个参数,将会自动调用push_back函数,扩展vector1的空间,如下:

    copy(deque1.begin(), deque1.end(), back_insert_iterator< vector<int> > (vector1));
    

    为了使插入迭代器更方便,STL定义了类属函数模板back_inserter:

    template <typename Container>
    inline back_insert_iterator<Container>
    back_inserter(Container& x){
        return back_insert_iterator<Container>(x);
    }
    

    这样copy就可以更简洁,如下:

    copy(deque1.begin(), deque1.end(), back_inserter(vector1));
    

    几种迭代器的适应范围:
    back_inserter 可以用于vector,deque,list。
    front_inerter 可以用于deque,list。(vector没有提供push_front)
    inserter 可以用于所有容器(包括关联容器)

    7. 流迭代器

    前面已经提及过了,即istream_iteratorostream_iterator,它们两个基本上是一样的用法。

    //使用ifstream流构造迭代器
    istream_iterator<T> s1(ifstream("a.txt"));
    //使用cin标准输入流构造迭代器
    istream_iterator<T> s2(cin);
    //下面的语句将构造一个空的迭代器,可以用于判断是否结束
    istream_iterator<T>()
    

    8. 常量迭代器

    常量迭代器就是const_iterator,它并不是指针不能变,而是迭代器所指的引用值不能变。当变量修饰为const,其迭代器必须是const_iterator,否则报编译错误。当迭代器特别复杂时,别忘了可以用auto:-)

    9. STL容器的迭代器分类

    容器 迭代器分类
    T a[n] 随机
    vector 随机
    deque 随机
    list 双向
    set 随机
    multiset 双向
    map 双向
    multimap 双向

    二、Miscellany

    @author gr  
    @mail   forgerui@gmail.com
  • 相关阅读:
    如果使用Excel oledb 导数据出现各种错误的解决方法
    如何对给定序列进行趋势预测
    Winform自定义控件之二叉树控件(2)
    WinForm自定义控件开发(1)
    .net 3.5 中的 服务器端回调
    Python内存管理
    oracle to mysql hibernate 实体id生成策略配置
    oracle to mysql
    mysql 删除所有表
    oracle函数在mysql用
  • 原文地址:https://www.cnblogs.com/gr-nick/p/3973125.html
Copyright © 2020-2023  润新知