几乎可以说,任何特定的数据结构都是为了实现某种特定的算法。STL容器就是将运用最广范的数据结构实现出来,允许程序员简单的使用常见的数据结构,减少不必要的重复造轮子的过程。
常用的数据结构有:数组(array) , 链表(list), tree(树),(stack), 队列(queue), 集合(set),映射表(map)……除去特殊的容器—容器适配器,根据数据在容器中的排列特性,这些数据结构可以分为顺序容器、关联容器和无序关联容器三种:

  1. 顺序容器:顺序容器实现能按顺序访问的数据结构。
    顺序容器可以视为一种各元素之间有顺序关系的线性表,或者一种线性结构的可序群集。> 顺序容器强调值的排序,其中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。
    顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。
    包括:vector(向量)、deque(队列)、list(列表)等…
  2. 关联容器:关联容器实现能快速查找( O(log n) 复杂度)的数据结构。
    关联容器是非线性的树结构,更准确的说是红黑树(平衡二叉树的一种)结构。与顺序容器不同,其各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序。> 关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能根据元素的特点“顺序地”获取元素。此时元素被视为有序的集合,默认在插入的时候按升序排列。
    关联式容器另一个显著特点是:在值中选择一个值作为关键字key,这个关键字对值起到索引的作用,方便查找。
    包括:set/multiset(集合/多重集合)、map/multimap(映射/多重映射)
  3. 无序关联容器:无序关联容器提供能快速查找(均摊 O(1) ,最坏情况 O(n) 的复杂度)的无序(哈希)数据结构。
    与关联容器不同,无序容器的底层采用哈希表的存储结构,但仍旧使用键值对(pair类型)的方式储存数据。因此,和关联容器相比,无序容器有以下两个特点:
    1. 无序容器内部存储的键值对是无序的,各键值对的存储位置取决于该键值对中的键
    2. 和关联式容器相比,无序容器擅长通过指定键查找对应的值(平均时间复杂度为 O(1))但对于使用迭代器遍历容器中存储的元素,无序容器的执行效率则不如关联式容器

包括:unordered_set、unordered_multiset、unordered_map、unordered_multimap

无序容器的底层实现原理,可以参见C++ STL无序容器底层实现原理(深度剖析)

  1. 容器适配器:本质上,适配器是使一种不同的行为类似于另一事物的行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。适配器是顺序容器的接口,它本身不能直接保存元素,它保存元素的机制是调用另一种顺序容器去实现,即可以把适配器看作“它保存一个容器,这个容器再保存所有元素”。
    STL 中包含三种适配器:栈stack 、队列queue 和优先级队列priority_queue 。

注意:

  1. 容器类自动申请和释放内存,因此无需new和delete操作。
  2. string并不是STL容器,但因为但是由于它的使用方法等等和STL容器很像,所以就把它当作STL容器一样介绍。

容器的通用操作

  1. 声明
    • 使用容器的时候需要包含相应的头文件,该头文件的名称与容器名称相同。
    • 容器可以使用包含几乎所有的类型,也可以在包含一个容器类型

例:

  1. #include<vector>
  2. std::vector<int> arr1;//等效于一维数组
  3. std::vector<int> arr2;//等效于二维数组

2.使用
每一个容器都是一个类,它们有自己的成员变量和成员函数,在STL库中,有很多的顺序容器的成员变量和成员函数是一样的。

  1. 成员变量:
    | 名称 | 说明 | | —- | —- | | iterator | 容器的迭代器 | | const_iterator | 可以读取元素,但是不能修改元素的迭代器 | | size_type | 无符号整型,有些容器可以使用下标访问的下标类型,最大不能超过容器大小 | | difference_type | 是二个指针相减结果的有符号整数类型,可以用于指代两个迭代器之间的距离 | | value_type | 元素类型 | | reference | 元素的左值类型,等同于value_type& | | const_reference | 元素的常量左值类型,等同于const value_type& |

  2. 构造函数(T表示容器类型):
    | 名称 | 说明 | | —- | —- | | T c | 默认构造 | | T c(c2) | 拷贝构造< c2—>c > | | T c(b,e) | 构造c,将迭代器b和迭代器e范围内的元素拷贝到c(array不支持) | | T c{a,b,c,d…} | 列表初始化c |

  3. 赋值与交换:
    | 名称 | 说明 | | —- | —- | | c1 = c2 | 将c2的值赋值给c1 | | c1 = {a,b,c,d…} | 将列表的内容赋值给c1 | | a.swap(b) | 交换a,b | | swap(a,b) | 同上 |

  4. 大小:
    | 名称 | 说明 | | —- | —- | | c.size() | 获取c中元素的个数(forward_list 不支持) | | c.max_size() | 获取最大可保存元素的数目 | | c.empty() | 如果c中的元素为空,则放回true,反之,false |

  5. 添加和删除元素(array不支持):
    | 名称 | 说明 | | —- | —- | | c.insert(args) | 将args中的元素拷贝进c | | c.emplace(inits) | 使用inits构造c中的一个元素 | | c.erase(args) | 删除args指定元素 | | c.clear() | 清空容器中的元素,返回void |

  6. 关系运算符:
    ==/!= ——所有的容器都支持等于和不等于运算符。

  7. 获取迭代器:
    | 名称 | 说明 | | —- | —- | | c.begin()/c.end() | 返回指向c的首元素/尾元素之后(超尾)的迭代器 | | c.cbegin()/c.cend() | 同上,返回的常量迭代器 const_iterator |

  8. 反向容器的额外成员(不支持 forward_list):
    | 名称 | 说明 | | —- | —- | | reverse_iterator | 按逆序寻址元素的迭代器(反向迭代器) | | const_reverse_iterator | 常量逆序迭代器 | | c.rbegin(),c.rend() | 返回c的尾元素和c的首元素之前的位置 |

注:该表格借鉴于C++primer