zoukankan      html  css  js  c++  java
  • CPP标准模板库 随笔

    对于无序容器而言,其次序是不固定的,就算添加一个元素,也可能全盘改变次序。唯一可以保证的是,内容相同的元素会相邻。(eg: 23,1,1,25,3,27,5,7,11,11)

    迭代器的种类:

      1,前向迭代器(Forward Iterator) 只能够以累加操作符向前迭代。 forward_list 的迭代器属于此类。其他容器如unordered_set , unordered_multiset, unordered_map 和 unordered_multimap也都至少是此类(但标准库其实为他们提供的是双向迭代器)

      2,双向迭代器(Bidirectional Iterator)以递增,递减进行前进或者后退。list set multiset map multimap

      3,  随机迭代器 (Random-access Iterator) 不但具备双向迭代器能力,还具备随机访问能力。具体的说,它们提供了迭代器算术运算的必要操作符(和寻常指针的算术运算完全对应)。你可以对迭代器增加或减少一个偏移量,计算两个迭代器之间的距离,

        或者使用 < 和 > 之类的relational操作符进行比较。vector , deque, array 和 string提供的迭代器都属于此类。

      4, 输入型迭代器 (Input Iterator) 向前迭代时能够读取/处理Value。 Input stream 迭代器就是这样一个例子。

      5, 输出型迭代器 (Output Iterator) 向前迭代时能够涂写value。Inserter 和 Output stream 迭代器属于此类。

    注意,为了写出与具体类型无关的代码,最好不要使用随机访问迭代器的特有操作。例如:

    //可以在任何容器使用
    for
    (auto pos = coll.begin(); pos != coll.end(); ++pos){ //... } //下面这个就不太适用了,list set map 不支持 operator <
    for(auto pos = coll.begin(); pos != coll.end(); ++pos){ //... }


    算法

    算法并非容器类的成员函数,而且搭配迭代器使用的全局函数。优势是,一次实现,所有容器可操作。大大提高了程序库的能力和弹性,大幅降低了代码量。

    注意,这不是OOP思维,而是泛型函数编程思维(generic functional programming paradigm)。缺陷,不似OOP中数据与操作紧密结合,代价是有失直观,其次某些数据结构和算法之间并不兼容。更甚,某些容器和算法虽然勉强兼容却毫无用处。因此,需要了解其缺陷,趋利避害。

    迭代器之适配器

    迭代器(Iterator)是个纯抽象的概念:任何东西,只要其行为类似迭代器,他就是一个迭代器。CPP标准库提供了数个预定义的特殊迭代器,亦即所谓的 迭代器适配器。它们不仅是辅助性质而已,它们赋予整个迭代器抽象概念更强大的威力。

      1,安插型迭代器(Inserter Iterator)

      2,串流迭代器 (stream Iterator)

      3, 逆向迭代器(Reverse Iterator)

      4, 搬移迭代器 (Move Iterator)(since c++11)

    Insert Iterator(安插型迭代器)

        插入而非覆写。目标区间会增大成长。

    int main(){
      list<int> coll1 = {1,2,3,4};
      vector<int> voll2;
    
      //把coll1的元素append到coll2中,采用apped
      copy( coll1.cbegin(), coll1.cend(),
             back_inserter(coll2));  
    
      //把coll1 插入 coll3前方,但顺序反向
      deque<int> coll3;
      copy( coll1.cbegin(), coll1.cend(),
             front_inserter(coll3)); 
    
      //复制coll1 到 coll4,唯一一个可以工作于关联集合的inserter
      set<int> coll4;
      copy( coll1.cbegin(), coll1.cend(),
             inserter(coll4, coll4.begin())); 
    }

    back_inserter(安插于容器末端) 内部调用push_back(),在容器尾部追加元素,适用于vector,deque,list 和 string
    front_inserter(安插于容器最前端) 内部调用push_front(),但元素反转。只能用于提供push_front()的容器。适用于deque,list和forword_list。
    General inserter,一般性的inserter,作用是“在初始化时接受之第二实参”所指的位置前方插入元素。内部调用insert(),所以STL容器都提供insert()函数,因此这是关联式容器唯一可用的预定义inserter。

    stream Iterator (串流迭代器)
    该迭代器用来读写stream,其提供了必要的抽象性,使得来自键盘的输入像是个集合,你能够从中读取内容。类似,你也可以把一个算法的输出结果重新导向导某个文件或屏幕上。

    #include<iterator>
    #include<algorithm>
    #include<vector>
    #include<string>
    #include<iostream>
    
    using namespace std;
    
    int main(){
        vector<string> coll;
        //从标准输入读取所有单词
        //源:所有string  目的:coll
        copy(istream_iterator<string>(cin),  // start of source
            istream_iterator<string>(),     // end of source
            back_inserter(cool));           //destination
    
            sort(coll.begin(),coll.end());
    
            unique_copy(coll.begin(),coll.end(),    //source
                        ostrem_iterator<string>(cout,"
    "));    //destination
    }
    参考链接:Stream Iterator(流迭代器)

    Reverse Iterator (反向迭代器)

     reverse iterator是STL中第三种预定义的迭代器适配器,该迭代器将以逆方向的进行所有的操作,它将递增运算(++)转换为递减运算(--),反之亦然。同时所有的容器都可以通过成员运算符rebegin()和rend()产生出 reverse iterators,也就是说反向迭代器是正向迭代器的适配器。

        vector<int> iVector;
        for (int i = 1; i <= 5; ++i)
        {
            iVector.push_back(i);
        }
     
        copy(iVector.rbegin(), iVector.rend(), ostream_iterator<int>(cout, " "));
        //5 4 3 2 1
        cout << endl;

      采用了reverse iterator迭代器后,copy()算法可以不用特殊处理,可以将++运算转换为--,将前向遍历改变为后向遍历,该程序反向输出vector中的数字序列,输出结果为:5 4 3 2 1。

    Move Iterator(搬移迭代器)

    来自C++11,后面再讲

    更易型算法(manipulating algorithm) 或 变易型算法(mutating algorithm)

    更易型算法指的是会“移除或重排或修改”元素的算法,是一组能够修改容器元素数据的模板函数,可进行序列数据的复制、交换、替换、填充、移除、旋转、随机抖动和分割。这些算法对迭代器有较高的要求,具体的迭代器类型随各个算法而定,或前向迭代器、或双向迭代器、又或者是随机迭代器,以提供算法所需要的迭代器操作。应用变易算法时,先要检查容器的迭代器是否符合要求,防止产生编译错误。

    STL学习笔记--变易算法

    stl变易算法(一)

    更易型算法若用于关联式容器或者无序容器,会出问题,关联式容器和无序容器不能被当作操作目标,原因很简单:如果更易型算法用于它们身上,会改变某些位置上的值,进而破坏容器本身对次序的维护。为避免累及内部次序,关联式容器和无序容器的所有迭代器均被声明为指向常量的value或者key。如果更改,只能调用成员函数。

     

    以函数作为算法的实参

    最简单的例子:for_each()算法,它针对区间内的每一个元素,调用一个由用户指定的函数:

    void print(int elem){
        cout << elem << ' ';
    }
    
    int main(){
        vector<int> coll;
        for(int i = 1; i <= 9;++i){
            coll.push_back(i);
        }
    
        for_each(coll.cbegin(),coll.cend(),print);
        cout << endl;
    }

    另一个例子是:std::transform

     函数对象(Function Object)

        传递给算法的“函数型实参”不一定得是函数,可以是行为类似函数的对象。这种对象称为函数对象,或者仿函数(functor)

    Wikipedia:函数对象  

  • 相关阅读:
    初学git(一):创建本地“仓库”
    git常用命令
    Linux学习(一):从图形界面进入命令行及命令行进入图形界面
    继承与派生
    数据类型和表达式
    UDP
    网络与通信
    枚举类型
    结构体
    第一个随笔
  • 原文地址:https://www.cnblogs.com/gardenofhu/p/9442156.html
Copyright © 2011-2022 走看看