zoukankan      html  css  js  c++  java
  • C++ STL结构总结

    1. 什么是STL

      它的全名是stand template library, 标准模板库,主要是将一些结构和算法写成模板,以便能够实现对任意类型的对象都可以操作,而不需要再一次去写一些算法及结构。

      它主要有以下三个概念:

        容器--容纳各种数据类型的结构,是类模板

        迭代器--类似于指针,指向容器内的对象的指针,主要用于指向元素

        算法--操作容器内的元素的运算函数,是函数模板,比如sort,find等排序算法,查找 算法,它与容器内元素类型无关

    2.  容器

      用于存放数据的容器可以分为三大类,顺序容器,关联容器,容器适配器:

      顺序容器--vector, list, deque

      关联容器--map, multimap, set, multiset

      容器适配器--stack, queue, priority_queue

    2.1 顺序容器

      顺序容器是无序的,插入的元素位置与值无关。

      vector容器,头文件<vector>, 是一个动态数据,元素在内存中是连续存放的,可以随意取vector中的元素。 

      deque, 头文件<deque>, 是一个双向队列,元素在内存中连续存放,可任意取容器中的元素,与vector中不一样的是,它存在一个头指针和一个尾指针,如

      list, 头文件<list>, 是一个双向链表,元素内存中不连续存放,易添加删除元素,不可随意存取元素。

    2.2 关联容器

      关联容器是有序的,插入元素的同时对新加元素进行排序,如何排序取决于元素类中<符号的成员函数重载, 所有的容器都是以平衡二叉树来实现,查找时间为O(lgn).

      set/multiset, 头文件<set>, 又称集合,两者唯一的区别是set不允许多个元素相等,而multiset则可以存放多个相等的元素,至于两个元素相等的定义为:

    如元素A不小于元素B,也不大于B,则A与B相等。因此在此仍需要重载容器内元素类的<符号函数,才能让容器函数对元素进行大小比较。

      map/multimap, 头文件<map>, 又称字典,元素内存在两个成员变量:first与second,它们一一对应,容器内以first的大小进行排序,first为key,second为first对应的值。multimap允许存在first相同的元素,而map则要求所有的元素first中值唯一。

    2.3 容器适配器

      stack,头文件<stack>, 栈,遵守先进后出的规则

      queue,头文件<queue>, 队列, 元素先进先出,如图

      priority_queue, 优先级队列,头文件<queue>, 内部以一定的顺序排列,优先级最高的元素第一个出列。

    2.4  容器中的成员函数

      顺序容器与关联容器的公有成员函数:

        begin-- 返回指向第一个元素的迭代器

        end--返回指向最后一个元素的后一个迭代器

        rbegin--返回指向最后一个元素的迭代器

        rend--返回指向第一个元素的前一个迭代器

        erase -- 删除容器中的一个或几个元素

        clear -- 删除容器内所有的元素

      顺序容器的成员函数:

        front -- 返回第一个元素的引用

        back -- 返回最后一个元素的引用

        push_back -- 在容器尾添加新元素

        pop_back -- 删除容器尾的元素

        erase -- 删除迭代器指向的元素或一个区间内的所有元素,返回删除元素的下一个元素的迭代器

      顺序容器list的成员函数:

        push_front: 在链表最前面插入元素

        pop_front: 删除链表最前面的元素

        sort : 排序

        reverse : 反转链表

        remove: 删除所有与指定值相等的元素

        unique: 删除所有与前一元素值相等的元素

        merge : 合并链表,并清空被合并链表

        splice : 在指定位置插入另一链表的一个或多个元素,并删除原来链表中的被插入元素

        注意: list的sort函数与vertor中的sort函数不同,主要是因为他们之间的迭代器不一样,现在看list的sort函数定义,

            list<T>  lt;

            lt.sort(compare);   //compare is a self defined function for comparing item T

            lt.sort();   // sort abided by symbol <, so we must redefined it in class T.

      容器适配器的成员函数:

        push : 添加元素

        top  : 返回栈顶或队头青元素引用

        pop : 删除一个元素  

    3. 迭代器

      类似于指针的用法,主要用于指向元素对象的位置,其定义如下:

        容器类名::iterator  it;

        容器类名::const_iterator  it;  //常量迭代器,不可修改对象的值

        容器类名::reverse_iterator  it; //反向迭代器, it++指向前一个元素,如果是正向迭代器,则指向下一个元素

      比较特殊的迭代器就是随机迭代器,可以进行操作 it + i, 直接跳进i个元素

    4. STL算法

      就是一些常用的数据结构算法,实现成各种模板函数,如min, max, find, find_if等等,由于此类函数太多,如果不常用,即使记住了也会容易忘掉。因此最好的办法就是理解他们实现的原理和方法,据我个人总结,可以分为以下几大类,其实如果仔细想想,可能会发现STL算法中的思想已经体现在上面的分类列举中了。

      算法, 也就是用模板实现的一些通用函数,即函数模板,可以操作任意类型(常用的int, double,自定义的类等,在这可以用模板类代替实现)。而通用的函数的功能无外乎就那么几样,比如说求最小值,最大值,排序,列表求和等,然而要想实现这些功能(假设排序),函数必须知道如何判断两个元素之间的大小才能进行排序,这里可分为两个版本, 在这以max_element为例,它的两个版本的定义如下:

        iterator max_element(iterator first, iterator last);  //求区间[first,last)之间最大的迭代值, 默认的大小比较为 < 符号, 需要在元素对象里重载

        iterator max_element(iterator first, iterator last, Pred op);// op 为一个函数指针或函数对象,if op(x,y)为真,则表示x<y, 该函数由自己定义,也可奖类对象重载()成员函数来实现。

      STL算法共包括3大类,常用函数方法,操作对象及操作对象的指针,即算法函数,模板类,迭代器。迭代器可以理解成指针,可以不管,现在我们已经明白了算法函数与模板类的分工,那就好办了。只要我们了解了算法函数的定义,即它的参数定义,我们就可以用它来处现模板类,而在模板类中只需要重载一些符号的成员函数即可,据个人认为,STL算法的核心就是模板类的符号重载,这不但保证了算法使用的灵活性和通常用,也能够让程序员实现一些特别的操作。

       在这里借用别人的一个例子,主要功能是用STL中的copy函数来实现打印数组,感觉比较好玩而且实用, 实现我们来看copy()函数的定义及源码实现。

    template<class InIt, class OutIt>
    OutIt copy(InIt first, InIt last, OutIt out) 
      copy区间[first, last)到out, 对区间内的所有元素都执行一次
                *(out+N) = *(first+N), 并返回out+N

    copy源代码

    template<class __II, class __OI>
    inline __OI copy(__II __f, __II __l, __OI __x)
    {
          for ( ; __f != __l; ++__f, ++__x)
                *__x = *__f;
          return __x;
    }

    定义一个ostream_iterator<int>对象,然后 通过cout输出一个个整数并以*号来分隔。

    ostream_iterator<int> output(cout,"*");
    copy(v.begin(), v.end(), output); // v为一个vector可变数组

    问题:copy函数如何才能将v中的数字打印出来呢?

    从源代码我们看出,里面的复制操作主要用到了++__x, *__x, =符号,而__x的类型原型实例化后就是ostream_iterator<int>, 因此只要重载了++,= , * 符号成员函数就可以达到刚才的要求了。

    首先自定义一个myostream类
    #include <iterator>
    template<class T>
    class my_osit:public iterator<output_iterator_tag,T>
    {
          private:
                 string sep;
                  ostream  &os;  //可用于写入文件
          public:
                  my_osit(ostream &o, string s):os(o), sep(s){}
                  void operator++(){}
                  my_osit & operator*() {return *this;}
                  my_osit & operator=(const T val)
                  {
                           os << val << sep;
                           return *this;
                  } 
    }    

    总得来说,STL算法很强大,如果能记住当然最好,如果记不住,如果学会 了查接口,灵活运用符号重载,写程序一样轻松。

  • 相关阅读:
    网站安全编程 黑客入侵 脚本黑客 高级语法入侵 C/C++ C# PHP JSP 编程
    【算法导论】贪心算法,递归算法,动态规划算法总结
    cocoa2dx tiled map添加tile翻转功能
    8月30日上海ORACLE大会演讲PPT下载
    【算法导论】双调欧几里得旅行商问题
    Codeforces Round #501 (Div. 3) B. Obtaining the String (思维,字符串)
    Codeforces Round #498 (Div. 3) D. Two Strings Swaps (思维)
    Educational Codeforces Round 89 (Rated for Div. 2) B. Shuffle (数学,区间)
    洛谷 P1379 八数码难题 (BFS)
    Educational Codeforces Round 89 (Rated for Div. 2) A. Shovels and Swords (贪心)
  • 原文地址:https://www.cnblogs.com/lovemo1314/p/4096310.html
Copyright © 2011-2022 走看看