1. 基本概念
- STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称,现在已经成为C++标准库的重要组成部分。
- STL的从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),容器和算法通过迭代器可以进行无缝地连接。
- STL实现了数据结构和算法的分离。
- STL具有高可重用性、高性能和高移植性的特点。
- 高可重用性:STL中几乎所有的代码都采用了类模板和函数模板的方式实现,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
- 高性能:STL采用了高效的数据结构和算法。
- 高移植性:STL是C++标准库的一部分,可以方便地跨项目、跨平台移植。
2. 容器
2.1. 容器的分类
- 序列式容器
- 每个元素都有固定位置,元素的位置取决于插入时机和地点,和元素值无关。
- vector、deque、list、stack、queue
- 关联式容器
- 元素位置取决于容器特定的排序准则,和插入顺序无关。
- set、multiset、map、multimap
- 常用容器列表
容器名 | 描述 | 头文件 |
---|
向量(vector) | 也称为动态数组,在内存中连续存储元素。它具有自动扩展大小的能力,支持随机访问和快速在末尾插入/删除元素。 | <vector> |
列表(list) | 也称为链表,由一系列节点链接而成。每个节点存储元素和指向下一个节点的引用。列表支持在任意位置插入/删除元素,但访问和搜索元素的性能较低。 | <list> |
双队列(deque) | 双向队列是一种特殊的队列,允许在两端进行插入和删除操作。它具有向量和列表的特性,可以高效地在队列的任一端添加或删除元素。 | <deque> |
集合(set) | 集合是一组唯一元素的容器,不允许重复。它提供了高效的搜索和插入操作,但不保持元素的顺序。 | <set> |
多重集合(multiset) | 多重集合类似于集合,但允许元素重复。 | <set> |
栈(stack) | 栈是一种后进先出(LIFO)的数据结构,类似于一堆盘子。元素只能从栈顶插入和删除。 | <stack> |
队列(queue) | 队列是一种先进先出(FIFO)的数据结构,类似于排队。元素只能从队列的一端插入,另一端删除。 | <queue> |
优先队列(priority_queue) | 优先队列是一种特殊的队列,元素按照优先级顺序进行插入和删除。具有最高优先级的元素始终排在队列的前面。 | <queue> |
映射(map) | 映射是一种键值对(Key-Value)的数据结构,每个键关联一个值。它提供了高效的键值查找,常见操作包括插入、删除和修改键值对。 | <map> |
多重映射(multimap) | 多重映射类似于映射,但允许多个键关联相同的值。 | <map> |
2.2. vector
2.2.1. 构造vector对象
- 默认构造
vector<T> vec;
- 带参构造
vector<T> vec(n);
vector<T> vec(n, val);
vector<T> vec1(n, val);
vector<T> vec2(vec1);
vector<T> vec2(vec1.begin(), vec1.end());
T arr[n] = {0};
vector<T> vec(arr, arr + n);
2.2.2. vector的赋值
vector<T> vec1(n, val), vec2;
vec2.assign(vec1.begin(), vec1.end());
vec2.assign(n, val);
vec2 = vec1;
vec2.swap(vec1);
2.2.3. vector的大小
vec1.size();
vec1.empty();
vec1.resize(num, val);
2.2.4. vector元素的访问
vec1[1];
vec1.at(1);
2.2.5. vector元素的插入与删除
vec1.front() = 2;
vec1.back() = 3;
vec1.push_back(3);
vec1.pop_back();
vec1.insert(vec1.begin() + 2, 3);
vec1.insert(vec1.begin() + 2, 2, 3);
vec1.insert(vec1.begin() + 2, vec1.begin(), vec1.end());
vec1.erase(vec1.begin() + 2);
2.2.6. vector中迭代器的使用
vector<T> vec1(n, val);
vector<T>::iterator it;
it = vec1.begin();
it = vec1.end();
vector<T>::reverse_iterator rit;
rit = vec1.rbegin();
rit = vec1.rend();
vector<T>::const_iterator cit;
cit = vec1.cbegin();
cit = vec1.cend();
vector<int>::const_reverse_iterator crit;
crit = vec1.crbegin();
crit = vec1.crend();
it = it + 2;
it = it - 2;
it++;
it--;
it == it + 2;
it != it + 2;
*it;
2.3. deque
- deque(double-ended queue,双端队列)是双端数组,而vector是单端的。
- 头部和尾部添加或移除元素都非常快速,但是在中部插入元素或移除元素比较费时。
- deque与vector的接口十分相似,主要多了两个函数。
push_front()
:在前端添加元素。pop_front()
:删除前端元素。
2.4. list
- list是一个双向链表容器,可高效地进行插入删除元素。
- list不可以随机存取元素,不支持索引访问元素。
- list的使用
ls.push_back(elem);
ls.pop_back();
ls.push_front(elem);
ls.pop_front();
ls.clear();
ls.remove(elem);
ls.reverse();
2.5. stack
- stack是堆栈容器,是一种“先进后出(FILO)”的容器。
- stack的使用
s.push(elem);
s.pop();
s.top();
while(!s.empty()){
cout << s.top() << endl;
s.pop();
}
2.6. queue
- queue是队列容器,是一种“先进先出(FIFO)”的容器。
- queue的使用
q.push(elem);
q.pop();
2.7. set/multiset
- set是一个集合容器,其中所包含的元素是唯一的(因此可用于去重),集合中的元素按一定的顺序排列(默认升序排序)。元素插入过程是按排序规则插入,所以不能指定插入位置。
- set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。
- set 不可以直接索引元素。
- multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
- 不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。
- set/multiset的使用
s.insert(elem);
s.erase(elem);
class Less{
bool operator()(const int& left, const int& right) const
{
return left > right;
}
}
set<int, Less> s;
it = s.find(elem);
s.count(elem);
s.lower_bound(elem);
s.upper_bound(elem);
pair<T1, T2> p = s.equal_range(elem);
p.first;
p.second;
2.8. map/multimap
- map是一个映射容器,能将两个元素通过键值对的形式关联起来。
- multimap允许多个键关联相同的值。
- map的使用
m.insert(pair(key,value));
m.insert(map<T1, T2>::value_type(key, value));
m[key] = value;
it->first;
it->second;
m[key];
m.at(key);
it = m.find(key);
3. 迭代器
- 迭代器是一种检查容器内元素并且遍历容器内元素的数据类型。
- 选代器提供对一个容器中的对象的访问方法并且定义了容器中对象的范围。
- 通过迭代器统一了对STL所有容器的访问方式。
- 删除或插入元素将导致正在使用的迭代器失效,可以接收插入或删除函数的返回值更新迭代器。