目录
定义
std::vector
是 C++ 标准模板库 (STL) 中的一个动态数组类模板,它提供了一个可以动态调整大小的数组。std::vector
是一种序列容器,它支持随机访问迭代器,因此可以高效地访问其内部的任何元素。
基本 API:
-
构造函数:
vector()
: 创建一个空的 vector。vector(size_type count, const T& value)
: 创建一个包含count
个元素,每个元素的值为value
的 vector。vector(const vector& other)
: 复制构造函数,创建一个包含其他 vector 所有元素的副本的 vector。
-
赋值和交换:
vector& operator=(const vector& other)
: 将当前 vector 赋值为另一个 vector。void swap(vector& other)
: 交换两个 vector 的内容。
-
元素访问:
reference operator[](size_type pos)
: 访问指定位置的元素。reference at(size_type pos)
: 访问指定位置的元素,提供边界检查。reference front()
: 返回第一个元素的引用。reference back()
: 返回最后一个元素的引用。pointer data() noexcept
: 返回指向底层数组的指针。
-
迭代器:
iterator begin() noexcept
: 返回指向第一个元素的迭代器。iterator end() noexcept
: 返回指向最后一个元素之后位置的迭代器。const_iterator cbegin() const noexcept
: 返回指向第一个元素的常量迭代器。const_iterator cend() const noexcept
: 返回指向最后一个元素之后位置的常量迭代器。
-
容量:
bool empty() const noexcept
: 检查 vector 是否为空。size_type size() const noexcept
: 返回 vector 中元素的数量。size_type capacity() const noexcept
: 返回 vector 当前可以容纳的元素数量。void reserve(size_type new_cap)
: 请求更改 vector 的容量。void shrink_to_fit()
: 请求收缩 vector 的容量以适应其大小。
-
修改容器:
void clear() noexcept
: 清空 vector 中的所有元素。void insert(iterator pos, const T& value)
: 在指定位置插入元素。void erase(iterator pos)
: 删除指定位置的元素。void push_back(const T& value)
: 在 vector 的末尾添加一个元素。void pop_back()
: 删除 vector 的最后一个元素。
使用说明:
- 使用
std::vector
前,需要包含头文件<vector>
。 std::vector
提供了动态增长的数组,可以在运行时动态调整大小。- 可以通过下标、迭代器等方式访问和修改 vector 的元素。
- 使用
push_back()
在末尾添加元素时,如果超出了当前容量,std::vector
会自动进行内存重新分配。 std::vector
会在末尾添加/删除元素时保持迭代器的有效性,但在中间位置添加/删除元素时可能会导致迭代器失效。
相对于其他容器的优势:
- 随机访问:
std::vector
支持高效的随机访问,通过下标可以在 O(1) 的时间复杂度内访问任意位置的元素。 - 连续存储: 元素在内存中是连续存储的,因此访问效率更高,尤其对于缓存友好。
- 动态增长: 可以动态增长和收缩,自动处理内存管理,使得插入和删除元素的操作更加高效。
- 标准容器:
std::vector
是 C++ 标准库的一部分,在 C++ 中被广泛使用,具有良好的兼容性和可移植性。
总体而言,std::vector
是 C++ 中最常用的容器之一,它在大多数情况下提供了高效的性能和便利的操作,特别适用于需要随机访问和动态调整大小的场景。
示例
向 vector 添加元素
有多种方法可以向 std::vector
添加元素:
-
使用
push_back
方法在 vector 的末尾添加一个元素:
vec.push_back(10);
-
使用
insert
方法在指定位置插入一个或多个元素:
vec.insert(vec.begin() + 1, 20); // 在第二个位置插入 20
-
使用
emplace
或emplace_back
方法在指定位置就地构造一个元素(避免不必要的拷贝或移动):
vec.emplace_back(30); // 在末尾就地构造一个值为 30 的元素
访问 vector 中的元素
使用下标运算符 []
或 at
方法来访问 vector 中的元素:
int first = vec[0]; // 使用下标运算符访问第一个元素
int second = vec.at(1); // 使用 at 方法访问第二个元素(会进行边界检查)
删除 vector 中的元素
-
使用
erase
方法删除指定位置的元素:
vec.erase(vec.begin() + 1); // 删除第二个元素
-
使用
pop_back
方法删除 vector 的最后一个元素:
vec.pop_back();
-
使用
clear
方法删除 vector 中的所有元素:
vec.clear();
获取 vector 的大小
使用 size
方法来获取 vector 的大小(即它包含的元素数量):
std::size_t size = vec.size();
判断 vector 是否为空
使用 empty
方法来检查 vector 是否为空:
if (vec.empty()) {
// vector 是空的
}
遍历 vector
使用迭代器或基于范围的 for 循环来遍历 vector:
// 使用迭代器遍历
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
// 使用基于范围的 for 循环遍历
for (const auto& elem : vec) {
std::cout << elem << " ";
}
vector 插入删除的复杂度
在 std::vector
中,插入和删除操作的时间复杂度取决于操作的位置。
-
尾部插入(
push_back
):- 时间复杂度:平摊 O(1)。
- 在尾部插入元素时,如果 vector 的容量仍有剩余,则时间复杂度是常数级别的,因为不需要重新分配内存;如果容量不足,需要重新分配内存,复杂度为 O(n),但这种情况是以均摊分析的方式出现的,即频繁插入时整体时间复杂度仍然是平摊 O(1)。
-
尾部删除(
pop_back
):- 时间复杂度:常数级别的 O(1)。
- 删除最后一个元素时,只需要将 size 减一,不涉及内存的移动或重新分配。
-
中间插入或删除(在给定位置进行插入或删除操作):
- 时间复杂度:O(n)。
- 插入或删除操作可能需要将操作点之后的所有元素向后或向前移动一个位置,以保持 vector 的连续性。这会导致需要线性时间来完成操作,因为在最坏情况下,需要移动操作点之后的所有元素。
因此,std::vector
的插入和删除操作的时间复杂度主要取决于插入/删除的位置,尾部操作具有较低的复杂度,而中间操作具有较高的复杂度。