一 、概括
容器分为顺序容器和关联容器,这种划分是基于容器中元素的组织方式。
容器名 | 中文名 | 头文件 | 所属概念 |
vector | 向量 | <vector> | 随机访问容器,顺序容器 |
deque | 双端队列 | <deque> | 随机访问容器,顺序容器 |
list | 列表 | <list> | 可逆容器,顺序容器 |
set | 集合 | <set> | 可逆容器,关联容器 |
multiset | 多重集合 | <set> | 可逆容器,关联容器 |
map | 映射 | <map> | 可逆容器,关联容器 |
multimap | 多重映射 | <map> | 可逆容器,关联容器 |
STL容器的共性:设S表示一种容器类型(例如vector<int>),s1和s2都是S类型的实例,容器支持的基本功能如下
操作 | 功能 |
S s1 | 容器都有一个默认构造函数,用于构造一个没有任何元素的空容器 |
s1 op s2 | 这里的op是各种比较运算符,它会对两个容器之间的元素按字典顺序进行比较 |
s1.begin() | 返回指向s1第一个元素的迭代器 |
s1.end() | 返回指向s1最后一个元素的下一个位置的迭代器 |
s1.clear() | 将容器s1的内容清空 |
s1.empty() | 返回一个布尔值,容器为空返回true,否则返回false |
s1.size() | 返回s1的元素个数 |
s1.swap(s2) | 将s1容器和s2容器的内容交换 |
二、顺序容器
STL中的顺序容器包括向量(vector)、双端队列(deque)和列表(list),它们在逻辑上可看作一个长度可扩展的数组,容器中的元素都是线性排列。可人为决定每个元素在容器中的位置,可以随时向指定的位置插入新的元素和删除已有的元素。
假设S表示容器的类型,s表示S类型的实例,用T表示S容器的元素类型,用t表示T类型的一个实例,用n表示一个整型数据,用p1和p2表示指向s中的元素的迭代器,用q1,q2表示任何一个指向T类型元素的输入迭代器(未必指向S中的元素,也未必具有S::iterator类型),顺序容器的基本功能如下所示:
S s | 使用默认构造函数,构造一个空容器 |
S s(n,t) | 构造一个由n个t元素构成的容器实例s |
S s(n) | 构造一个有n个元素的容器实例s,每个元素都是T() |
S s(q1,q2) | 使用 [q1,q2) 区间内的数据作为s的元素构造s |
可以使用赋值函数assign将指定的元素赋给顺序容器,顺序容器中原先的元素会被清除,赋值函数的3种形式是与构造函数一一对应的
s.assign(n,t) | 赋值后的容器由n个t元素构成 |
s.assign(n) | 赋值后的容器由n个值都为T()的元素构成 |
s.assign(q1,q2) | 赋值后的容器的元素为 [q1,q2) 区间内的数据 |
向顺序容器中可以一次插入一个或多个指定元素,也可以将一个迭代器区间所表示的序列插入,插入时需要通过一个指向当前容器元素的迭代器来指示插入位置。
s.insert(p1,t) | 在s容器中p1所指向的位置插入一个新的元素t,插入后的元素夹在原p1和p1-1所指向的元素之间,该函数会返回一个迭代器指向新插入的元素 |
s.insert(p1,n,t) | 在s容器中p1所指向的位置插入n个新的元素t,插入后的元素夹在原p1和p1-1所指向的元素之间,没有返回值 |
s.insert(p1,q1,q2) | 将 [q1,q2) 区间内的元素顺序插入到s容器中p1位置处,新的元素夹在原p1和p1-1所指向的元素之间 |
s1.erase(p1) | 删除s1容器中p1所指向的元素,返回被删除元素的下一个元素的迭代器 |
s1.erase(p1,p2) | 删除s1容器中 [p1,p2) 区间内的元素,返回最后一个被删除元素的下一个元素的迭代器(即在删除前p2所指向元素的迭代器) |
s1.resize(n) | 将容器的大小变为n,如果原来的元素大于n,则容器末尾多余的元素会被删除,如果原来的元素小于n,则在容器末尾会用T()填充 |
s.front() | 获得容器首元素的引用 |
s.back() | 获得容器尾元素的引用 |
s.push_back(t) | 向容器尾部插入元素t |
s.pop_back() | 将容器尾部的元素删除 |
s.push_front(t) | 向容器头部插入元素t (向量除外) |
s.pop_front() | 将容器头部的元素删除 (向量除外) |
三、关联容器
简介:对于关联容器,它的每个元素都有一个键(key),容器中的元素的顺序并不能人为随意决定,而是按照键的取值升序排列的。也就是说,对于一个关联容器s,使用迭代器在 [s.begin(),s.end() )区间内遍历,访问到的序列总是升序的。
分类:按照容器中是否允许出现重复键值,关联容器可分为单重关联容器和多重关联容器,单重关联容器中的键值是唯一的,不允许重复,集合和映射属于这一类;多重关联容器中,相同的键值允许重复出现,多重集合和多重映射属于这一类。按照键与元素的关系可以分为简单关联容器和二元关联容器。简单关联容器以元素本身作为键,集合和多重集合属于这一类;二元关联容器的元素是由键和某种类型的附加数据共同构成,键只是元素的一部分,映射和多重映射属于这一类
类型 | 简单管理容器 | 二元关联容器 |
单重关联容器 | 集合(set) | 映射(map) |
多重关联容器 | 多重集合(multiset) | 多重映射(multimap) |
补充:二元关联容器的元素类型是键类型和附加数据类型的组合,这种组合类型可以用一个二元组(pair)来表示,pair是<utility>头文件中定义的结构体模板:
template<class T1,class T2>
struct pair{
T1 first; //二元组的第一元
T2 second; //二元组的第二元
pari(); //默认构造函数
pair(const T1 &x,const T2 &y); //构造first=x,second=y的二元组
template<class U,class V>pair(const pair<U,V>&p); //复制构造函数
};
假设S表示容器的类型,s表示S类型的实例,用T表示S容器的元素类型,用t表示T类型的一个实例,用K表示S容器的键的类型,用k表示K的一个实例,用n表示一个整型数据,用p1和p2表示指向s中的元素的迭代器,用q1,q2表示任何一个指向T类型元素的输入迭代器,关联容器的基本功能如下所示:
操作 | 功能 | 单重关联容器 | 多重关联容器 |
S s | 构造一个空容器 | 构造一个空容器 | 构造一个空容器 |
S s(q1,q2) | 将 [q1,q2)区间的数据作为s的元素构造s | 当[q1,q2)范围内出现具有相同键的元素时,只有一个元素会被加入s中 | [q1,q2)范围内的所有元素均被无条件加入s中 |
操作 | 功能 | 单重关联容器 | 多重关联容器 |
s.insert(t) | 将元素t插入s容器中 | 只有当不存在相同键的元素时才能成功插入,该函数返回类型为pair<S::iterator,bool>。插入成功时,返回被插入元素的迭代器,否则返回与t的键相同的元素的迭代器和false | 插入总会成功,返回已插入元素的迭代器 |
s.insert(p1,t) | 将元素t插入s容器中,p1是一个提示的插入位置,如果提示位置准确(即t的键的大小刚好在p1-1和p1之间)则可以提高插入效率。即使提示位置不准确也可以正确完成插入操作,该函数总是返回一个迭代器 | 只有当不存在相同键的元素时才能成功插入,插入成功时,返回被插入元素的迭代器,否则返回与t的键相同的元素的迭代器 | 插入总会成功,返回已插入元素的迭代器 |
s.insert(q1,q2) | 相当于按顺序对 [q1,q2) 区间内的每个元素x分别执行s.insert(x) | 略 | 略 |
s.erase(p1) | 删除p1所指向的元素 |
s.erase(p1,p2) | 删除 [p1,p2) 区间内的元素 |
s.erase(k) | 删除所有键为k的元素,返回被删除元素的个数 |
s.find(k) | 找到任意一个键为k的元素,返回该元素的迭代器,如果s中没有键为k的元素,则返回s.end() |
s.lower_bound(k) | 得到s中第一个键值不小于k的元素的迭代器 (第一个>=k的元素) |
s.upper_bound(k) | 得到s中第一个键值大于k的元素的迭代器 (第一个>k的元素) |
s.equal_range(k) | 得到一个用pair<S::iterator,S::iterator>表示的区间,记为 [p1,p2) 。该区间刚好包含所有键值为k的元素,p1==s.lower_bound(k)和p2==s.upper_bound(k)一定成立 |
s.count(k) | 得到s容器中键为k的元素个数 |
注:关联容器的插入和删除操作不会使任何已有的迭代器、指针或引用失效。