算法竞赛中C++ vector的常规操作

发布时间 2023-07-04 13:54:52作者: Amαdeus

算法竞赛中 C++ vector 的常规操作

对 vector 的理解

vector 官方将其翻译为向量,但实际上是变长动态数组,其可以存放各种类型的对象。

vector 定义语法

大致格式:vector<类型> 数组名

在初始情况下,vector的大小是0,也就是空的数组。下面都以int型举例。

vector<int> v;           //定义一个空的数组
vector<int> v1(v);       //拷贝数组v到数组v1中,相当于v和v1完全一样

vector<int> v2(10);       //定义一个长度为10的数组,数组中的值默认为0
vector<int> v3(10, 233);  //定义一个长度为10的数组,所有值都初始化为233(如果初始化值为0,则和上面一个例子结果是一样的)

vector<int> v4 = {1, 2, 3};   //初始化vector为{1,2,3},数组大小为3。等价于vector<int> v4{1,2,3},但我个人不喜欢用

vector<int> v5;
v5.resize(10);            //定义了一个v5数组,并且将其大小变为10。如果元素少,后面会用0补齐;如果元素多,会自行删除多余地元素。

PS:存放不同元素类型的vector不能进行拷贝操作哦?。



vector 存放元素类型举例

  1. 常用数据类型及对象示例
vector<int> v1;          //存储int型变量的vector
vector<long long> v2;    //存储long long型变量的vector
vector<double> v3;       //存储double型变量的vector
vector<string> v4;       //存储string型变量的vector
  1. 其他常用对象示例
  • struct 自定义的结构体,这个没什么好说的
struct node{
    int a, b, c;
    ...
};

vector<node> v;     //存储结构体
  • pair<类型1,类型2>,假设当前的pair名为p, 若要访问p中的第一个数据,其格式为p.first; 同样的,若要访问p中的第二个数据,其格式为p.second。
vector<pair<int, int>> v1;             //存储pair类型
vector<pair<char, int>> v2; 
vector<pair<string, int>> v3;
vector<pair<pair<int, int>, int>> v4;  //pair嵌套
  1. vector表示 多维数组
vector<int> v[5];    //表示一个长度为5的数组,每个位置存放了一个变长数组vector,这种形式比较常见。

vector<vector<int>> vv;  //二维vector, 这种形式在leetcode中很多,尤其是与图相关的问题


vector 常规操作

  1. vector 的遍历

在了解 vector 的遍历之前,需要先知道几个东西。第一个是 begin(),其表示指向 vector 头部指针;第二个是 end(),其表示指向 vector 尾部的指针,这里的尾部并不是最后一个元素的位置,而是最后一个元素后面一个位置,可以理解成是一个空的位置。

还有一个补充的是 size(),这个函数返回的是 vector 的大小。

还有就是 rbegin()rend(),其中 rbegin() 即vector反转后的开始指针返回(其实就是原来的end-1),rend() 即vector反转构的结束指针返回(其实就是原来的begin-1)。这两个用的比较少,不必要掌握。

  • 方式一
for(int i = v.begin(); i != v.end(); i ++ ) cout << v[i] << ' ';

//也可以指定区间遍历
for(int i = v.begin() + 1; i != v.begin() + 4; i ++ ) cout << v[i] << ' ';

//输出元素的方式也可以写成 v.at(i),和v[i]结果是一样的,at()比较安全,主要是可以在越界的时候可以报错,不过一般用不到。
for(int i = v.begin(); i != v.end(); i ++ ) cout << v.at(i) << ' ';

  • 方式二
for(int i = 0; i < v.size(); i ++ ) cout << v[i] << ' ';
for(int i = 0; i < (int)v.size(); i ++ ) cout << v[i] << ' ';
//这里推荐写成(int)v.size()的形式,比较安全。size()返回值的类型本质上不是int, 只不过可以和int兼容使用。

//千万不要写成 i <= v.size() - 1,大概率会出问题的


  • 方式三

这是我最喜欢的,也是最简洁的方式。

//auto表示自动判别数据类型, x是存放于v中的元素,是按照顺序读取的,缺点是必须完整地读出v中地所有数据
for(auto x : v) cout << x << ' ';   

//x前面加一个引用号,可以使得x可以更改,同时也会快一些,所以总的来说我最喜欢这个
for(auto &x : v){         
    x = 1;
    cout << x << endl;      
}

还有一种迭代器遍历的方式,这个从来没用过,写得很繁琐,不需要掌握。


  1. 增加元素 push_back()

vector 比较常用的是从尾部增加元素,在中间插入或者其他形式在算法竞赛中不常用,反正我从来没有用过。

vector<int> v;

v.push_back(1);
for(auto &x : v) cout << x << ' '; 

v.push_back(2);
v.push_back(3);
for(auto &x : v) cout << x << ' '; 

  1. 删除元素 pop_back()

只要掌握 pop_back() 就行,其他什么 erase 删除中间元素什么地我从来没用过,没必要掌握。

补充一个函数 empty(),可以用于判断vector是否为空。

vector<int> v = {1, 2, 3, 4, 5};

if(v.empty()) puts("数组为空");

while(!v.empty()) v.pop_back();

if(v.empty()) puts("数组为空")

  1. 返回首部元素和尾部元素 front(), back()
vector<int> v = {1, 2, 3};

cout << v.front() << endl;   //返回首部元素

cout << v.back() << endl;    //返回尾部元素

  1. 清空数组 clear()
vector<int> v = {1, 2, 3};

v.clear();

if(v.empty()) puts("数组为空");


vector 的其他用法

  1. 排序 sort()

sort 同样可以用于 vector 上,具体格式如下:

vector<int> v = {5, 3, 2, 1, 8, 3};

sort(v.begin(), v.end());

for(auto &x : v) cout << x << ' ';

  1. 翻转 reverse()
vector<int> v = {5, 3, 2, 1, 8, 3};

reverse(v.begin(), v.end());

for(auto &x : v) cout << x << ' ';

  1. 判断相等
vector<int> v1 = {1, 2, 3}, v2 = {1, 2};

if(v1 == v2) puts("相等");
else puts("不相等");