1、什么是vector?
(1)std::vector
是 STL 提供的 内存连续的、可变长度 的数组(亦称列表)数据结构。能够提供线性复杂度的插入和删除,以及常数复杂度的随机访问。(2)Vectors 包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线性时间复杂度。
2、为什么要使用 vector?
1、vector
可以动态分配内存很多时候我们不能提前开好那么大的空间(eg:预处理 1~n 中所有数的约数)。尽管我们能知道数据总量在空间允许的级别,但是单份数据还可能非常大,这种时候我们就需要
vector
来把内存占用量控制在合适的范围内。vector
还支持动态扩容,在内存非常紧张的时候这个特性就能派上用场了。
2、vector
重写了比较运算符及赋值运算符
vector
重载了六个比较运算符,以字典序实现,这使得我们可以方便的判断两个容器是否相等(复杂度与容器大小成线性关系)。例如可以利用vector<char>
实现字符串比较(当然,还是用std::string
会更快更方便)。另外vector
也重载了赋值运算符,使得数组拷贝更加方便。
3、vector
便利的初始化由于
vector
重载了=
运算符,所以我们可以方便的初始化。此外从 C++11 起vector
还支持 列表初始化,例如vector<int> data {1, 2, 3};
。
3、vector
的创建
// 1. 创建空vector; 常数复杂度
vector<int> v0;
// 1+. 这句代码可以使得向vector中插入前3个元素时,保证常数时间复杂度
v0.reserve(3);
// 2. 创建一个初始空间为3的vector,其元素的默认值是0; 线性复杂度
vector<int> v1(3);
// 3. 创建一个初始空间为3的vector,其元素的默认值是2; 线性复杂度
vector<int> v2(3, 2);
// 4. 创建一个初始空间为3的vector,其元素的默认值是1,
// 并且使用v2的空间配置器; 线性复杂度
vector<int> v3(3, 1, v2.get_allocator());
// 5. 创建一个v2的拷贝vector v4, 其内容元素和v2一样; 线性复杂度
vector<int> v4(v2);
// 6. 创建一个v4的拷贝vector v5,其内容是{v4[1], v4[2]}; 线性复杂度
vector<int> v5(v4.begin() + 1, v4.begin() + 3);
// 7. 移动v2到新创建的vector v6,不发生拷贝; 常数复杂度; 需要 C++11
vector<int> v6(std::move(v2)); // 或者 v6 = std::move(v2);
4、元素访问
at()
v.at(pos)
返回容器中下标为pos
的引用。如果数组越界抛出std::out_of_range
类型的异常。
operator[]
v[pos]
返回容器中下标为pos
的引用。不执行越界检查。
front()
v.front()
返回首元素的引用。
back()
v.back()
返回末尾元素的引用。
data()
v.data()
返回指向数组第一个元素的指针。
5、迭代器
begin()/cbegin()
返回指向首元素的迭代器,其中
*begin = front
。
end()/cend()
返回指向数组尾端占位符的迭代器,注意是没有元素的。
rbegin()/crbegin()
返回指向逆向数组的首元素的逆向迭代器,可以理解为正向容器的末元素。
rend()/crend()
返回指向逆向数组末元素后一位置的迭代器,对应容器首的前一个位置,没有元素。
6、与长度相关:
empty()
返回一个bool
值,即v.begin() == v.end()
,true
为空,false
为非空。
size()
返回容器长度(元素数量),即std::distance(v.begin(), v.end())
。
resize()
改变vector
的长度,多退少补。补充元素可以由参数指定。
max_size()
返回容器的最大可能长度。与容量相关:
reserve()
使得vector
预留一定的内存空间,避免不必要的内存拷贝。
capacity()
返回容器的容量,即不发生拷贝的情况下容器的长度上限。
shrink_to_fit()
使得vector
的容量与长度一致,多退但不会少。
7、元素增删及修改
clear()
清除所有元素insert()
支持在某个迭代器位置插入元素、可以插入多个。复杂度与pos
距离末尾长度成线性而非常数的erase()
删除某个迭代器或者区间的元素,返回最后被删除的迭代器。复杂度与insert
一致。push_back()
在末尾插入一个元素,均摊复杂度为 常数,最坏为线性复杂度。pop_back()
删除末尾元素,常数复杂度。swap()
与另一个容器进行交换,此操作是 常数复杂度 而非线性的。
8、代码示例:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v0;//创建一个v0向量
v0.reserve(3);//设置v0最小的元素容纳数量
for(int i = 1; i <= 10; i++)//将1~10的数字填入向量中
v0.push_back(i);//在v0最后添加一个元素
cout<<"first element :" << v0.front() << endl;//返回v0第一个元素
cout<< "last element :" << v0.back()<<endl;//返回v0最后一个元素
cout << "number of elements:" << v0.size() << endl;
v0.clear();//清空
cout<<"Number of elements:" << v0.size() << endl;
return 0;
}
运行结果:
3、依次从头删除(迭代器)
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v0;//创建一个v0向量
for (int i = 1; i <= 10; i++)//将1~10的数字填入向量中
v0.push_back(i);//在v0最后添加一个元素
int size = v0.size();//设置v0长度
vector<int>::iterator startIt;
vector<int>::iterator tempIt;
for (int i = 0; i < size; i++)
{
startIt = v0.begin();
v0.erase(startIt);
//Display the vector
for (tempIt = v0.begin(); tempIt != v0.end(); tempIt++)
{
cout << *tempIt;
}
cout << endl;
}
return 0;
}
程序运行结果: