分类
Level6

STL模板

STL(standard template library 标准模板库或者泛型库)是C++标准库的重要组成部分,其包含有大量的模板类和模板函数。STL 是一些容器、算法和其他一些组件的集合,所有容器和算法都是总结了几十年来算法和数据结构的研究成果。STL的核心包括以下三个组件:STL中的所有组件都是由模板(templete)组成,其元素可以是任意类型。
一、容器(containers):容器可分为 顺序式容器关联式容器

  • 顺序式容器:是一种各个元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。顺序容器的元素排列次数与元素值无关,而是由元素添加到容器里的次序决定。顺序容器包括:
    • vector:动态数组,从任何地方快速插入与删除。
    • stack:栈,后进先出。
    • list:双链表,从任何地方快速插入与删除。
    • queue:队列,先进先出。
    • deque:双向队列,从前面或后面快速插入与删除,直接访问任何元素。
    • priority_queue:优先队列,最高优先级元素总是第一个出列。
  • 关联式容器:关联式容器是非线性的树结构更准确的说是二叉树结构。各个元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序。但是关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能够根据元素的特点“顺序地”获取元素。元素是有序的集合,默认在插入的时候按升序排列。关联式容器包括:
    • set:集合,快速查找,不允许重复值。
    • multiset:快速查找,允许重复值。
    • map:一对一映射,基于关键字快速查找,不允许重复值。
    • multimap:一对多映射,基于关键字快速查找,允许重复值。

容器选择的场景

  • deque的使用场景:比如排队购票系统,对排队者的存储可采用deque,支持头端的快速移除,尾端的快速添加。如果采用vector,则头端移除时,会移动大量的数据,速度慢。
  • vector 与 deque的比较:
    • (1)vector.at()比deque.at()效率高,比如vector.at(0)是固定的,deque的开始位置却是不固定的。
    • (2)如果有大量释放操作的话,vector花的时间更少,这根二者的内部实现有关。
    • (3)deque支持头部的额快速插入与快速移除,这是deque的优点。
  • list的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确定位置元素的移除插入。
  • set的使用场景:比如手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
  • map的使用场景:比如按ID号存储十万个用户,想要快速通过ID查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是vector容器,最坏的情况下可能要遍历完整个容器才能找到该用户。

此外,还有string,bitset等拟容器,可以更加高效地进行字符处理、位处理等操作。
注意:STL容器在有些场合下(比如查询关键字)发生预期外结果会返回尾后迭代器(end())表示未找到或错误。而当出现非法访问(例如访问超出vector范围的元素),则可能会抛出异常。

二、迭代器(iterators)
迭代器的作用与指针类似,可通过引用操作(*)访问其所指向的元素内容
常用的容器(如map,set,vector等)都可以使用一对迭代器来表示,即begin(指向容器的第一个元素)和end(指向该容器最后一个元素之后的位置)。空序列或空容器的begin()==end()。使用迭代器可以遍历STL容器内全部或部分元素的对象,或指出容器中的一个特定位置。
迭代器共有5个类别:输入迭代器,输出迭代器,前向迭代器,双向迭代器,随机迭代器。
迭代器常用操作如下:
* 返回当前位置上的元素值。如果该元素有成员,可以通过迭代器以 -> 操作取用。
++ 将迭代器前进至下一个元素。
==或!= 判断两个迭代器是否指向同一位置。
= 为迭代器赋值(即将所指元素的位置赋值过去)

三、STL中的常用算法函数
算法(algorithms)是一类C++ algorithm 头文件中所提供的模版函数。