zoukankan      html  css  js  c++  java
  • ###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
  • 相关阅读:
    SGU 495 Kids and Prizes 概率DP 或 数学推理
    poj 2799 IP Networks 模拟 位运算
    uva 202 Repeating Decimals 模拟
    poj 3158 Kickdown 字符串匹配?
    uva 1595 Symmetry 暴力
    uva 201 Squares 暴力
    uva 1594 Ducci Sequence 哈希
    uva 1368 DNA Consensus String 字符串
    数字、字符串、列表的常用操作
    if条件判断 流程控制
  • 原文地址:https://www.cnblogs.com/gr-nick/p/3973125.html
Copyright © 2011-2022 走看看