文章目录
1.概述
vector 翻译为“向量”,也可称为“变长数组”,即“长度根据需要而自动改变的数组”。
vector 动态增长的原理:当插入新元素的时候,如果空间不足,那么 vector 会重新申请更大的一块内存空间,将原空间数据拷贝到新空间,释放旧空间,再把新元素插入到新申请空间。
2.vector的定义与初始化
头文件 include <vector>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> v1; // int类型的空vector
vector<string> v2; // string类型的空vector
vector<int> v3(20, -10); // 创建20个int类型的元素,每个元素的值为-10
vector<string> v4(15, "hello"); // 创建15个string类型的元素,每个元素的值为hello
vector<int> v5(20); // 创建20个int类型的元素,每个元素值默认为0
vector<string> v6(15); // 创建15个string类型的元素,每个元素值默认为空串
vector<int> v7(v3); // 通过拷贝构造函数初始化
vector<string> v8 = v4; // 通过拷贝构造函数初始化
vector<int> v9(v3.begin(), v3.end());
return 0;
}
在 C++11 标准中,可以用列表初始化方法给值,即用 {}
括起来。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> v1(10); // 创建10个int类型的元素,每个元素值为0
vector<int> v2{10}; // 创建1个int类型的元素,该元素的值为10
vector<int> v3(10, 1); // 创建10个int类型的元素,每个元素值为1
vector<int> v4{10, 1}; // 创建2个int类型的元素,元素值分别为10和1
vector<string> v5 = {"aaa", "bbb", "ccc"};
vector<string> v6(10); // 创建10个string类型的元素,每个元素值默认为空串
vector<string> v7{10}; // 创建10个string类型的元素,每个元素值默认为空串
vector<string> v8(10, "hello"); // 创建10个string类型的元素,每个元素值默认为hello
vector<string> v9{10, "hello"}; // 创建10个string类型的元素,每个元素值默认为hello
return 0;
}
3.vector的赋值
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v1;
v1.assign(5, 1); // 将5个1赋值给v1
vector<int> v2;
v2.assign(v1.begin(), v1.end()); // 将v1的[begin,end)赋值给v2
vector<int> v3;
v3 = v1;
return 0;
}
4.vector的元素个数
size()
用来获得 vector 中元素的个数,时间复杂度为
O
(
1
)
O(1)
O(1)。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{10, 20, 30, -10, -20, -30};
cout << v.size() << endl; // 6
return 0;
}
5.vector尾部添加或删除元素
push_back(x)
就是在 vector 后面添加一个元素 x
,时间复杂度为
O
(
1
)
O(1)
O(1)。
pop_back()
用以删除 vector 的最后一个元素,时间复杂度为
O
(
1
)
O(1)
O(1)。
vector 在尾部添加或删除元素非常快。在中间操作非常耗时,因为它需要移动元素。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v;
v.push_back(11);
v.push_back(22);
v.push_back(33);
v.pop_back();
cout << v.size() << endl; // 2
return 0;
}
6.判断两个vector是否相等
如果两个 vector 的元素数量相等并且对应位置的元素值也相等,那么这两个 vector 就相等,否则不相等。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v1 = {100, 200, 300, -10, -20, -30};
vector<int> v2 = {100, 200, 300, -1, -2, -3};
if (v1 == v2)
{
cout << "v1 == v2" << endl;
}
else
{
cout << "v1 != v2" << endl;
}
return 0;
}
7.vector的遍历
vector 容器可以随机存取元素。
7.1 [ ] 运算符
和访问普通数组一样,对于 vector 容器来说,直接访问 v[index]
即可。当然,这里的下标 index
是从 0
到 v.size()-1
,访问这个范围外的元素可能会运行出错。
[]
方式,如果越界或出现其他错误,不会抛出异常,可能崩溃,可能数据随机出现。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{10, 20, 30, -10, -20, -30};
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
return 0;
}
7.2 at()
at()
方式,如果越界或出现其他错误,会抛出异常,需要捕获异常并处理。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{10, 20, 30, -10, -20, -30};
for (int i = 0; i < v.size(); i++)
{
cout << v.at(i) << " ";
}
cout << endl;
return 0;
}
7.3 范围for
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {100, 200, 300, -10, -20, -30};
for (auto &x : v)
{
x *= 2;
}
for (auto &x : v)
{
cout << x << endl;
}
return 0;
}
7.4 迭代器iterator
迭代器可以理解为一种类似于指针
的东西,通过迭代器我们可以读容器中的元素值,还可以修改某个迭代器所指向的元素值。
迭代器的定义如下,iter
就是一个 vector<typename>::iterator
类型的变量,其中 typename
就是定义 vector 时所填写的类型。
vector<typename>::iterator iter;
v[i]
和 *(v.begin()+i)
是等价的。需要注意的是,在常用 STL 容器中,只有在 vector 和 string 中,才允许使用 v.begin()+i
这种迭代器加上整数的写法。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{10, 20, 30, -10, -20, -30};
vector<int>::iterator iter = v.begin();
for (int i = 0; i < v.size(); i++)
{
cout << *(iter + i) << " ";
}
cout << endl;
return 0;
}
7.4.1 begin()与end()
begin()
返回的迭代器指向容器中的第一个元素。
end()
返回的迭代器指向容器中的最后一个元素的下一个位置。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> v1;
v1.push_back('h');
v1.push_back('e');
v1.push_back('l');
v1.push_back('l');
v1.push_back('o');
vector<char>::iterator iter1 = v1.begin();
cout << *iter1 << endl;
vector<char>::iterator iter2 = v1.end() - 1;
cout << *iter2 << endl;
return 0;
}
如果一个容器为空,则 begin() 和 end() 返回的迭代器相同。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> v;
vector<char>::iterator iter1 = v.begin();
vector<char>::iterator iter2 = v.end();
if (iter1 == iter2)
{
cout << "容器v为空" << endl;
}
return 0;
}
迭代器支持自增、自减操作,于是可以通过如下代码遍历 vector 中的元素。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{10, 20, 30, -10, -20, -30};
for (vector<int>::iterator iter = v.begin(); iter != v.end(); iter++)
{
cout << *iter << " ";
}
cout << endl;
return 0;
}
注意:在使用迭代器的过程中,千万不要改变 vector 容器的容量(不要增加或删除 vector 容器中的元素),否则迭代器会失效。
7.4.2 front()与back()
front()
返回头部元素的引用,可以当左值。
back()
返回尾部元素的引用,可以当左值。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<char> v1;
v1.push_back('h');
v1.push_back('e');
v1.push_back('l');
v1.push_back('l');
v1.push_back('o');
cout << "v1.front() = " << v1.front() << endl;
cout << "v1.back() = " << v1.back() << endl;
v1.front() = 'w';
v1.back() = 'd';
cout << "v1.front() = " << v1.front() << endl;
cout << "v1.back() = " << v1.back() << endl;
return 0;
}
7.5 反向迭代器reverse_iterator
7.5.1 rbegin()与rend()
rbegin()
返回一个反向迭代器,指向反向迭代器的第一个元素。
rend()
返回一个反向迭代器,指向反向迭代器的最后一个元素的下一个位置。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v{10, 20, 30, -10, -20, -30};
for (vector<int>::reverse_iterator riter = v.rbegin(); riter != v.rend(); riter++)
{
cout << *riter << endl;
}
return 0;
}
7.6 常量迭代器const_iterator
vector<int>::iterator iter
可以修改指针的地址,也可以修改指向的元素值。
vector<int>::const_iterator iter
相当于 const char *p
,可以修改指针的地址,但不能修改指向的元素值。const_iterator 对象可以用于 const容器 或 非const容器。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
const vector<int> v1 = {100, 200, 300}; // const容器
vector<int>::const_iterator iter1 = v1.begin(); // vector本身是const类型,其迭代器也是const类型
*iter1 = 4; // 错误
iter1++; // 正确
vector<int> v2 = {100, 200, 300}; // 非const容器
vector<int>::const_iterator iter2 = v2.begin(); // vector本身是非const类型,其迭代器也是非const类型
*iter2 = 4; // 错误
iter2++; // 正确
return 0;
}
const vector<int>::iterator iter
相当于 char * const p
,可以修改指向的元素值,但不能修改指针的地址。const 的 iterator 只能用于 非const 容器。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {100, 200, 300}; // 非const容器
const vector<int>::iterator iter = v.begin();
*iter = 4; // 正确
iter++; // 错误
return 0;
}
7.6.1 cbegin()与cend()
C++11 引入了两个新函数:cbegin() 和 cend() 返回的都是常量迭代器。
如果容器本身不是 const 类型,但是在某些情况下数据不应该被修改,这时可以通过 cbegin() 和 cend() 返回 const 类型的迭代器,以避免数据被意外修改。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {100, 200, 300}; // 非const容器
for (vector<int>::const_iterator iter = v.cbegin(); iter != v.cend(); iter++)
{
*iter = 4; // 错误
cout << *iter << endl;
}
return 0;
}