是STL容器中的一种常用的容器,由于其大小(size)可变,常用于数组大小不可知的情况下来替代数组。vector容器与数组十分相似,被称为动态数组。时间复杂度为O(1)。
数组数据通常存储在栈中,vector数据通常存储在堆中。
动态扩展不是在原空间后加入空间,而是寻找更大空间,将数据拷贝新空间,释放新空间。
头文件:#include <vector>
迭代器类似于指针,提供了对象的间接访问,但获取迭代器并不是使用取地址符。如果将指针理解为元素的“地址”,那么迭代器可以理解为元素的“位置”。可以使用迭代器访问某个元素,迭代器也能从一个元素移动到另一个元素。
一个迭代器的范围由一对迭代器表示,分别为 begin 和 end。其中 begin 成员返回指向第一个元素的迭代器;end 成员返回容器最后一个元素的下一个位置(one past the end),也就是指向一个根本不存在的尾后位置。
vector初始化
vector<T> v1 创建一个名为v1是元素类型为T的空vector
vector<int> v2 (n): 创建一个vector,元素类型为int,元素个数为n,值默认为0
vector<int> v3 {1,2,3,4,5} vector有5个数,注意花括号
vector<int>v4 (4,1) vector由4个值为1组成
vector<int>v5 (v4) 将v4所有值复制到v5中
vector<int>v6(v3.begin(), v3.end()) 将v3的值从头到尾复制到v6
vector<int>v7(v3.rbegin(), v3.rend()) 将v3的值从尾到头复制到v7
cbegin 和begin()功能相同,在其基础上增加了 const 属性,不能用于修改元素。
cend 和end()功能相同,在其基础上增加了 const 属性,不能用于修改元素。
crbegin 和rbegin()功能相同,在其基础上增加了 const 属性,不能用于修改元素。
crend 和rend()功能相同,在其基础上增加了 const 属性,不能用于修改元素。
vector方法
v2.empty() 判断v2是否为空,为空返回true,否则返回false
v2不为空,返回3
if(v2.empty()) {
return 2;
}else{
return 3;
}
元素长度
v2.size() 返回实际v2中的元素个数
int len = v2.size();
v2.capacity()返回v2中可以容纳的元素个数
区分:capacity 当前vector分配的大小,size 当前使用数据的大小
v2.resize()改变v2中的实际元素个数
v2.reserve()增加v2 的容量
访问元素
operator[] 用于从vector中访问指定元素,它接受一个索引并返回指定位置元素的引用。语法:
vector::operator[size_type n];
例如:v2[n] 是v2第n个位置元素的引用,不能用于下标操作添加元素,像v2[7]=5是错的。vector容器的下标也是从0开始计数的。
vector.at(i)等同于vector[i],访问数组下表的元素,例如:v2.at(2) 返回下标为2的值的元素
两者区别:虽然两者访问元素都不能越界,但是operator不做边界检查,哪怕越界也会返回一个引用(错误的),at会做边界检查,如果越界,会抛出std::out_of_range异常。
cout<<v2[3]<<endl;
cout<<v2.at(3)<<eendl;
v2.front()返回第一个元素
v2.back()返回最后一个元素
v2.data()返回v2第一个元素的指针
元素排序
sort 需要头文件 #include <algorithm>
sort(v2.begin(), v2.end())一种是两个参数,一般为升序(由小到大)
sort(v2.begin(), v2.end(), t),是三个参数,第三个参数可以写排序规则,一般搭配lambda表达式的捕获列表使用
vector<int> a{0,10,9,8,1,5,2,3,6,4,7};
bool cmp(int x,int y){return x>y;}
sort(a.begin(), a.end(),cmp);
//两者等价
sort(a.begin(), a.end(),[](int x, int y){return x > y;});
//原有形式,省略是因为C++可以自动识别函数返回值得数据类型
sort(a.begin(), a.end(),[](int x,int y) -> bool {return x>y;} );
reverse(v2.begin(), v2.end()) 逆序输出
reverse(a.begin(), a.end()); // 原位逆序排列
//结果
7 4 ....9 10 0
unique(v2.begin(), v2.end())将输入序列相邻的重复项“消除”,一般搭配sort使用,先排序后消除。
例如,0 0 0 0 3 5 输出后 0 3 5
交换元素
v2.swap() 交换v2 其中的两个元素的所有内容
swap() 函数在头文件 <algorithm>
和 <utility>
中都有定义,使用时引入其中一个即可。
v2.assign() 用新元素替换所有内容
添加元素
向 vector 容器中添加元素的唯一方式就是使用它的成员函数,如果不调用成员函数,非成员函数既不能添加也不能删除元素。
v3.push_back(v) 在v3尾端添加一个值为v的元素
v3.push_back(5);
cout<<v3<<endl;
//结果 1,2,3,4,5,5
v2.emplace_back() 在尾部添加一个元素
vector<int> values{};
values.emplace_back(1);
values.emplace_back(2);
for (int i = 0; i < values.size(); i++) {
cout << values[i] << " ";
}
//结果1 2
两者区别在于底层实现的机制不同。push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
插入元素
v2.insert(pos,elem)在迭代器 pos 指定的位置之前插入一个新元素elem
iterator insert(pos,n,elem) | 在迭代器 pos 指定的位置之前插入 n 个元素 elem,并返回表示第一个新插入元素位置的迭代器。 |
iterator insert(pos,first,last) | 在迭代器 pos 指定的位置之前,插入其他容器(不仅限于vector)中位于 [first,last) 区域的所有元素,并返回表示第一个新插入元素位置的迭代器。 |
iterator insert(pos,initlist) | 在迭代器 pos 指定的位置之前,插入初始化列表(用大括号{}括起来的多个元素,中间有逗号隔开)中所有的元素,并返回表示第一个新插入元素位置的迭代器。 |
插入有很多种形式
vector<int> demo{1,2};
//第一种格式用法
demo.insert(demo.begin() + 1, 3);//{1,3,2}
//第二种格式用法
demo.insert(demo.end(), 2, 5);//{1,3,2,5,5}
//可以看出end指的不是数组最后一位,而是最后一位的下一个位置
//第三种格式用法
array<int,3>test{ 7,8,9 };
demo.insert(demo.end(), test.begin(), test.end());//{1,3,2,5,5,7,8,9}
//第四种格式用法
demo.insert(demo.end(), { 10,11 });//{1,3,2,5,5,7,8,9,10,11}
v2.emplace() 指定位置前插入一个新元素,emplace() 每次只能插入一个元素,而不是多个。
vector<int> demo1{1,2};
//emplace() 每次只能插入一个 int 类型元素
demo1.emplace(demo1.begin(), 3);
for (int i = 0; i < demo1.size(); i++) {
cout << demo1[i] << " ";
}
//结果 3 1 2
emplace与insert比较,emplace效率更高,因为,insert需要将新元素将其生成,再将其拷贝或复制到容器中,emplace是直接在容器指定位置构造元素。
删除元素
v3.pop_back();
//结果 从1 2 3 4 5 5 变为1 2 3 4 5
vector<int>demo{ 1,2,3,4,5 };
auto iter = demo.erase(demo.begin() + 1);//删除元素 2
for (int i = 0; i < demo.size(); i++) {
cout << demo[i] << " ";
}
//iter迭代器指向元素 3
cout << endl << *iter << endl;
//结果
1 3 4 5
3
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
vector<int>demo{ 1,2,3,4,5 };
//交换要删除元素和最后一个元素的位置
swap(*(std::begin(demo)+1),*(std::end(demo)-1));//等同于 swap(demo[1],demo[4])
//交换位置后的demo容器
for (int i = 0; i < demo.size(); i++) {
cout << demo[i] << " ";
}
demo.pop_back();
cout << endl << "size is :" << demo.size() << endl;
cout << "capacity is :" << demo.capacity() << endl;
//输出demo 容器中剩余的元素
for (int i = 0; i < demo.size(); i++) {
cout << demo[i] << " ";
}
return 0;
}
//结果
1 5 3 4 2
size is :4
capacity is :5
1 5 3 4
vector<int> demo{ 1,2,3,4,5 };
//删除 2、3
auto iter = demo.erase(demo.begin()+1, demo.end() - 2);
for (int i = 0; i < demo.size(); i++) {
cout << demo[i] << " ";
}
//结果
1 4 5
vector<int>demo{ 1,3,3,4,3,5 };
//交换要删除元素和最后一个元素的位置
auto iter = remove(demo.begin(), demo.end(), 3);
//输出剩余的元素
for (auto first = demo.begin(); first < iter;++first) {
cout << *first << " ";
}
//结果
1 4 5
长度仍为6
注意,在对容器执行完 remove() 函数之后,由于该函数并没有改变容器原来的大小和容量,因此无法使用之前的方法遍历容器,而是需要向程序中那样,借助 remove() 返回的迭代器完成正确的遍历。
remove() 的实现原理是,在遍历容器中的元素时,一旦遇到目标元素,就做上标记,然后继续遍历,直到找到一个非目标元素,即用此元素将最先做标记的位置覆盖掉,同时将此非目标元素所在的位置也做上标记,等待找到新的非目标元素将其覆盖。因此,demo为1 3 3 4 3 5,删除3,得到的结果为 1 4 5 4 3 5
。
过程:3做标记,3再做标记,4覆盖第一个3,做标记,3再做标记,5覆盖第二个3,做标记。
所以,可以使用 erase() 成员函数删掉这些 "无用" 的元素。
vector<int>demo{ 1,3,3,4,3,5 };
//交换要删除元素和最后一个元素的位置
auto iter = remove(demo.begin(), demo.end(), 3);
demo.erase(iter, demo.end());
//输出剩余的元素
for (int i = 0; i < demo.size();i++) {
cout << demo[i] << " ";
}
//结果 1 4 5
长度变为3
vector<int>demo{ 1,3,3,4,3,5 };
//交换要删除元素和最后一个元素的位置
demo.clear();
cout << "size is :" << demo.size() << endl;
cout << "capacity is :" << demo.capacity() << endl;
//结果
size is :0
capacity is :6
二维数组
完整版:vector<vector<int>> table(size1, vector<int>(size2, 0)); 行列都给了
名为table的vector容器包含元素为vector的容器。列为size2,行为size1,值为0。
省略版:vector<vector<int>> table; 行列未知
vector<vector<int>> table(5); 行为5,也就是长度
获取二维数组长度
int size_row = table.size(); //获取行数
int size_col = table[0].size(); //获取列数
访问二维数组
for (int i = 0; i < a.size(); i++)
{
for (int j = 0; j < a[0].size(); j++)//注意如果arr为空不可直接arr[0]
{
cout << a[i][j] << endl;
}
}
https://blog.csdn.net/aruewds/article/details/117375364
C++ STL vector插入元素(insert()和emplace())详解 (biancheng.net)
http://t.csdnimg.cn/Ej3rl
http://t.csdnimg.cn/ebFXf
使用lambda表达式实现sort的自定义排序 - octal_zhihao - 博客园 (cnblogs.com)