1. 定义及类型
- 顺序容器将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素,这就是顺序容器。
- 顺序容器类型有:vector,list和deque。顺序容器适配器包括:stack,queue,priority_queue。
- 所有容器类型都定义了默认构造函数,用于创建指定类型的空容器对象。默认构造函数不带参数。三种顺序容器必须包含的头文件如下:
#include<vector>
#include<list>
#include<deque>
2. 容器元素的初始化
- C<T> c;
- 创建一个名为c的空容器,C是容器类型名,T是元素类型。适用于所有容器。
- C<T> c(c2);
- 创建c2的副本;c和c2必须具有相同的容器类型,并存放相同类型的元素。适用于所有容器。
- C<T> c(b,e);
- 创建c,其元素是迭代器b和e标示的范围内元素的副本。适用于所有容器。
- C<T> c(n,t);
- 用n个值为t的元素创建容器c,只适用于顺序容器。
- C<T> c(n);
- 创建有n个值初始化元素的容器c,只适用于顺序容器。
- 注解:接收容器大小做形参的构造函数只适用于顺序容器,关联容器不支持这种初始化。
3. 常用迭代器运算
*iter
iter->mem
++iter
iter++
--iter
iter--
iter1==iter2
iter1!=iter2
此外,vector和deque容器的迭代器还提供额外的运算(list容器不支持如下迭代器操作),如下:
iter+n
iter-n
iter1+=iter2
iter1-=iter2
iter1-iter2
>,>=,<,<=
4. 顺序容器的操作
4.1 容器定义的类型别名
- size_type 无符号类型,足以存储此容器类型的最大可能长度
- iterator 迭代器
- const_iterator 只读型迭代器,不能修改容器内的元素
- reverse_iterator 按逆序寻址元素的迭代器
- const_reverse_iterator 只读逆序迭代器
- difference_type 足够存储两个迭代器差值的有符号整型,可为负数
- value_type 元素类型
- reference 元素的左值类型,是value_type&的同义词
- const_reference 元素的常量左值类型,等效于const value_type&
4.2 begin和end成员
- c.begin() 返回一个迭代器,它指向容器c的第一个元素
- c.end() 返回一个迭代器,它指向容器c的最后一个元素的下一位置
- c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素
- c.rend() 返回一个逆序迭代器,它指向容器c的第一个元素前面的位置
4.3 在顺序容器中添加元素的操作
- c.push_back(t) 在容器c的尾部添加值为t的元素,返回void类型
- c.push_front(t) 在容器c的前端添加值为t的元素,返回void类型。只适用于list和deque
- c.insert(p,t) 在迭代器p所指向的元素前面插入值为t的元素,返回指向新元素的迭代器
- c.insert(p,n,t) 在迭代器p所指向的元素前面插入n个值为t的元素,返回void类型
- c.insert(p,b,e) 在迭代器p所指向的元素前面插入由迭代器b和e标记范围内的元素,返回void类型
- 关键概念
- 容器元素都是副本,即容器内的元素发生变化时,被复制的原值不会受到影响。
- 使用迭代器插入单个元素返回指向新插入元素的迭代器;插入多个元素时,返回void类型
4.4 所有容器都是通过比较其元素来实现容器的关系运算,如果容器元素不支持关系运算,则该比较运算符不合法。
4.5 容器大小的操作
- c.size() 返回容器c中的元素个数。返回类型为c::size_type
- c.max_size() 返回容器c可容纳的最多元素个数,返回类型为c::size_type
- c.empty() 返回容器大小是否为0的布尔值
- c.resize(n) 调整容器c的长度大小,使其能容纳n个元素。如果n<c.size(),则删除多出来的元素;否则,添加采用值初始化的新元素。
- c.resize(n,t) 调整容器c的长度大小,使其能容纳n个元素。所有新添加的元素值都为t
4.6 访问元素
- c.back() 返回容器c的最后一个元素的引用
- c.front() 返回容器c的第一个元素的引用
- c[n] 返回下标为n的元素的引用。只适用于vector和deque
- c.at(n) 返回下标为n的元素的引用,越界会抛出out_of_range异常。只适用于vector和deque
4.7 删除元素
- c.erase(p) 删除迭代器p所指向的元素,返回指向被删除元素的后面元素的迭代器。
- c.erase(b,e) 删除迭代器b和e所标记的范围内所有的元素。返回指向被删除元素段的后面元素的迭代器
- c.clear() 删除容器c内的所有元素。返回void
- c.pop_back() 删除容器c的最后一个元素。返回void
- c.pop_front() 删除容器c的第一个元素,返回void。只适用于list和deque
4.8 赋值与swap
- c1=c2 删除容器c1的所有元素,然后将c2的所有元素复制给c1.
- c1.swap(c2) 交换容器c1和c2的元素
- c.assign(b,e) 重新设置c的元素,将迭代器b和e标记范围内的所有元素复制到c中。
- c.assign(n,t) 将容器c重新设置为存储n个值为t的元素
- 注解:带有一对迭代器参数的assign操作允许我们将一个容器的元素赋给另一个不同类型的容器。
4.9 vector容器的自增长
size是指当前拥有的元素个数,而capacity则指容器在必须分配新存储空间之前可以存储的元素总数;reserve则告诉容器最初分配时应该预留多少个元素的存储空间,这样可以容器元素个数达到指定值之前不需要频繁调整容器容量大小。
注解:string类型也支持capacity和reverse操作。
4.10 容器的选用
- vector,list,deque的特性与区别
- 与vector一样,在deque的中间insert或者erase元素效率比较低;
- 不同于vector,deque在其首部实现insert和erase的高效操作,就像在容器尾部一样;
- 与vector容器一样而不同于list容器的是,deque容器支持对所有元素的随机访问;
- 在deque容器首部或者尾部插入元素不会使任何迭代器失效,而在首部或者尾部删除元素则只会使指向被删除元素的迭代器失效。在deque容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器失效。
- 选择容器类型的法则
- 如果程序要求随机访问元素,则应使用vector或deque容器;
- 如果程序必须在容器的中间插入或删除元素,则应采用list容器;
- 如果程序在容器首部或尾部插入或删除元素,则应采用deque容器;
- 如果只需在读取输入时在容器的中间位置插入元素,然后需要随机访问,则可考虑在输入时将元素读入到一个list容器,接着对此容器排序,使其适合顺序访问,然后将排序后的list容器复制到一个vector容器。
4.11 容器适配器
- 适配器通用的操作和类型
- size_type 一种类型,足以存储此适配器类型最大对象的长度
- value_type 元素类型
- container_type 基础容器的类型,适配器在此容器类型上实现
- A a; 创建一个新的空适配器,命名为a
- A a(c) 创建一个名为a的新适配器,初始化为容器c的副本
- 关系操作符 所有适配器支持全部关系操作符
- 栈适配器
- 栈提供的所有操作:
- s.empty() 如果栈为空,则返回true;否则返回false
- s.size() 返回栈中元素的个数
- s.pop() 删除栈顶元素,但不返回其值
- s.top() 返回栈顶元素的值,但不删除该元素
- s.push(item) 在栈顶压入新元素
- 队列和优先级队列
- q.empty() 队列为空则返回true,否则返回true
- q.size() 返回队列中的元素个数
- q.pop() 删除队首元素,但不返回其值
- q.front() 返回队首元素的值,但不删除该元素。该操作只适用于队列
- q.back() 返回队尾元素的值,但不删除该元素。该操作是适用于队列
- q.top() 返回具有最高优先级的元素值,但不删除该元素。该操作只适用于优先级队列
- q.push(item)
- 对于queue,在队尾压入一个新元素;
- 对于priority_queue,在基于优先级的适当位置插入新元素
- 栈提供的所有操作: