C++的STL内容回顾
C++的STL模板
1.1 什么是STL
STL(Standard Template Library),即标准模板库
STL的一个特点是数据结构和算法的分离。例如,由于STL的sort()函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组;
STL另一个重要特性是它不是面向对象的。STL主要依赖于模板而不是封装,继承和虚函数(多态性)——OOP的三个要素。
1.2 STL六大组件
- 容器(Container),是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器;
- 迭代器(Iterator),提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定义了operator*()以及其他类似于指针的操作符地方法的类对象;
- 算法(Algorithm),是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;
- 仿函数(Function object)
- 适配器(Adaptor)
- 空间配制器(allocator)
1.2.1 容器
STL容器包括序列式容器和关联式容器
容器类自动申请和释放内存,无需new和delete操作。
序列式容器:每个元素都有固定位置,有vector、deque、list;
Vector:将元素置于一个动态数组中管理,可以随机存取元素(用索引直接存取)。
特点:
(1)
一个动态分配的数组(当数组空间内存不足时,都会执行: 分配新空间-复制元素-释放原空间);
(2) 当删除元素时,不会释放限制的空间,所以向量容器的容量(capacity)大于向量容器的大小(size);
(3) 对于删除或插入操作,执行效率不高,越靠后插入或删除执行效率越高;
(4) 高效的随机访问的容器。
Deque:双端队列,可以随机存取元素(用索引直接存取)。
特点:
(1) 具有分段数组、索引数组, 分段数组是存储数据的,索引数组是存储每段数组的首地址;
(2) 向两端插入元素效率较高!
(若向两端插入元素,如果两端的分段数组未满,既可插入;如果两端的分段数组已满,
则创建新的分段函数,并把分段数组的首地址存储到deque容器中即可)。
中间插入元素效率较低!
List:双向链表,不提供随机存取(顺序遍历访问)
特点:
(1)元素访问只能通过遍历链表的方式进行;
(2)任意元素的插入删除操作都十分迅速。
关联式容器:元素位置取决于特定的排序准则,与插入或删除顺序无关。有set、multiset、
map、multimap。
特点:
(1) 关联式容器都是有序的,升序排列,自动排序;
(2) 实现的是一个平衡二叉树,每个元素都有一个父节点和两个子节点,
左子树的所有元素都比自己小,右子树的所有元素都比自己大;
Set/multiset: 构造set集合的主要目的是为了快速检索,去重与排序
特点:
(1)
set存储的是一组无重复的元素,而multiset允许存储有重复的元素;
(2) 如果要修改某一个元素值,必须先删除原有的元素,再插入新的元素。
Map/multimap:
特点:
(1)
map为单重映射、multimap为多重映射;
(2) 主要区别是map存储的是无重复键值的元素对,而multimap允许相同的键值重复出现,既一个键值可以对应多个值。
(3) map内部自建了一颗红黑二叉树,可以对数据进行自动排序,所以map里的数据都是有序的,这也是我们通过map简化代码的原因。
(4)自动建立key-value的对应关系,key和value可以是你需要的任何类型。
(5) key和value一一对应的关系可以去重
1.2.2 迭代器
Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
迭代器的作用:能够让迭代器与算法不干扰的相互发展,最后又能无间隙的粘合起来。用以操作复杂的数据结构,容器提供迭代器,算法使用迭代器;常见的一些迭代器类型:iterator、const_iterator、reverse_iterator和const_reverse_iterator
1.2.3 算法
算法部分主要由头文件,和组成
是所有STL头文件中最大的一个,它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。
体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
中则定义了一些模板类,用以声明函数对象。
STL中算法大致分为四类:
1)非可变序列算法:指不直接修改其所操作的容器内容的算法。
2)可变序列算法:指可以修改它们所操作的容器内容的算法。
3)排序算法:对序列进行排序和合并的算法、搜索算法以及有序序列上的集合操作。
4)数值算法:对容器内容进行数值计算。
1.2.4 仿函数
在STL的历史上,仿函数(functor)是早期的命名,C++标准规格定下来后采用了新的名称——函数对象(function object)。就实际意义而言,函数对象的称谓更加贴切:一种具有函数特质的对象。
在C++中,函数调用操作符是指左右小括弧
() ,该操作符是可以重载的。许多 STL 算法都提供了两个版本,一个用于一般情况(例如排序时使用 operator< 以递增方式排列),一个用于特殊情况(例如排序时按照使用者自定义的大小关系进行排序)。
1.2.5 适配器
适配器在STL组件中,扮演者轴承、转换器的角色。将一个class 的接口转换为另一个 class 的接口,使原本因接口不兼容而不能合作的 class,可以一起运作。
STL提供的适配器分为三类:
1、容器适配器,改变容器的接口
2、迭代器适配器,改变迭代器的接口
3、仿函数适配器,改变仿函数的接口
1.2.5.1 容器适配器
STL提供了两个容器适配器,分别是 stack(栈) 和 queue(队列)。他们是修饰 deque(双端队列)的接口而呈现出另一种容器风貌
1.2.5.2 迭代适配器
STL提供了许多应用于迭代器身上的配接器,包括 insert iterators、reverse iterators、iostream iterators
1.2.5.3 仿函数适配器
1.2.5.3 空间适配器
(https://blog.csdn.net/qq_26822029/article/details/82915529)
参考
[1]https://blog.csdn.net/shenaisi/article/details/81545418?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160802321119195265154411%252522%25252C%252522scm%252522%25253A%25252220140713.130102334…%252522%25257D&request_id=160802321119195265154411&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-8-81545418.pc_search_result_no_baidu_js&utm_term=STL
[2]http://ibillxia.github.io/blog/2014/11/15/insight-into-stl-6-functor-or-function-objects/
[3]https://blog.csdn.net/weixin_39640298/article/details/88767303