C++与传统的C语言有一个很大的区别,就是新增了规范模板库 STL(Standard Template Library),它是 C++ 规范库的一部分,不须要独自装置,只须要 #include 对应的头文件即可。
本文将介绍STL中最根底的一个容器:vector
留神:本文仅从入门和实用角度介绍vector的用法。如有不谨严的中央欢送斧正!
引入头文件
在应用vector之前须要用#include <vector>
来引入头文件。
如果你是比赛选手,也能够用万能头#include <bits/stdc++.h>
其中蕴含了<vector>
。
vector简介
vector能够了解为动静数组,它的大小会随着元素的减少而主动增大。下标从0
开始,大小为n
的vector的可用范畴是[0, n - 1]
。
vector中不仅能够寄存int, char
等根底数据类型,还能够寄存构造体、类
等等。
然而一个vector中只能寄存一种类型。
初始化
当初咱们能够入手来生成一个vector试试:
vector<int> v(3, 5);//生成一个vector,其中有3个值为5的元素
二维数组前面会讲到。
遍历数组
既然是数组必定少不了遍历嘛对吧~
思路是,先用v.size()
获取vector的大小,而后用for循环遍历。
//v.size()返回值为unsigned intfor(int i = 0;i < v.size(); ++ i){ printf("%d", v[i]);}//后果为: 5 5 5
在C++11之后,能够应用auto
关键字进行遍历,这个在前面会讲到。
插入元素
void push_back(const T& x)
vector有一个叫push_back()
的办法,能够在数组尾部插入一个元素且令数组大小+1。
举个例子:
printf("%d\n", (int)v.size());//v.size() = 3for(int i = 1;i <= 3; ++ i)v.push_back(i);//当初 v 是: 5 5 5 1 2 3//v.size() = 6
个别只向尾部插入元素,因为向其余地位插入元素的复杂度较高。
删除元素
void pop_back()
删除最初一个元素。void clear()
清空vector,大小变为0void erase(iter l, iter r)
清空迭代器指向的区间$[l, r)$的元素。
v.pop_back();//5 5 5 1 2v.clear();//null
其余的个别也用不着。
判断是否为空
bool empty()
判断vector是否为空
vector<int> a(3);//v.empty() == falsea.clear();//v.empty() == true
一些罕用函数(以下 v 指实例对象)
v.resize(n)
将vector大小批改为nv.begin()
获取vector第一个元素的迭代器(指针)v.end()
获取vector最初一个元素的后一个地位的迭代器v.rbegin()
获取vector倒数第一个元素的迭代器(指针)v.rend()
获取vector倒数最初一个元素的后一个地位的迭代器
vector<int> v = {1, 2, 3}cout << *v.begin() << '\n';//1cout << *v.rbegin() << '\n';//3cout << *(++ v.begin()) << '\n';//2
留神迭代器只能++
或者--
,不能够做 += n
这种操作!
欢送在右上角留下邮箱订阅我的博客哦!每周更新优质算法、计算机、互联网文章!
一些实例用法
上面介绍一些vector的实例化用法。
auto关键字遍历vector
有时候用auto
关键字是一件很美的事儿,比方在写dfs的时候,不必管子节点的程序,间接往下递归即可,用auto
比用下标来写循环更平安。
须要留神一点,auto
默认为浅拷贝,也就是复制出的一个副原本进行遍历,如果想要遍历vector自身,须要加个&
,看以下的例子就明确了。
vector<int> v = {1, 5, 2, 4, 3};for(auto i : v)i = 1;//v = {1, 5, 2, 4, 3}for(auto &i : v)i = 1;//v = {1, 1, 1, 1, 1}
当然你也本人尝试,把地址打进去看看。
而且,用&
会比间接浅拷贝更快。
vector排序
给vector排序,须要先引入<algorithm>
头文件:
#include <algorithm>using namespace std;int main(){ vector<int> v = {5, 1, 3, 2, 4}; sort(v.begin(), v.end());//传入vector的首尾迭代器 //v = {1 2 3 4 5}}
这样排序默认是升序的,能够利用reverse(iterator first, iterator last)
进行翻转,写法和sort相似:
reverse(v.begin(), v.end());//v = {5, 4, 3, 2, 1}
如果想在排序的时候一步到位排成降序,能够自定义比拟函数,这里不再赘述。
排序并去重
在做离散化时常常用到vector,因为它能够不便的进行排序去重。
unique(iterator first, iterator last)
能够将反复的元素挪动到开端的地位,前提是vector升序。
对于vectorv = {1, 1, 2, 5}
,unique(v.begin(), v,end())
的后果为:v = {1, 2, 5, 1}
并返回v.begin() + 3
示意去重后的起点地位(即无效数组的最初一个元素的下一个地位)。
vector<int> v = {1, 5, 2, 2, 1, 7, 7};sort(v.begin(), v.end());v.erase(unique(v.begin(), v.end()), v.end());//v = {1, 2, 5, 7}
二维数组
起始就是把vector外面存的元素改为vector,就是套娃。vector<vector<int> > v2;
这样会产生一个大小为0
的二维数组。
你能够通过resize()
为每一个行设置一个大小,从而产生每一行都大小不同的二维数组:
vector<vector<int> > v2; v2.resize(3); for(int i = 0;i < 3; ++ i)v2[i].resize(i + 1); /* v = { {0} {0, 0} {0, 0, 0} }; 有点神奇 */
在做邻接表的时候常常应用vector,然而我习惯于开vector数组,即上面这种写法:
vector<int> g[maxn];
值得注意的一点(性能)
vector尽管能够动静开拓空间,然而这也是有代价的。
vector的空间不是一个一个开的,而是每当元素个数超出了以后的空间,就会开拓一个大小为原先两倍(也有说法是1.5倍)的空间,而后再将本来的数据拷贝过来,这就会增大vector的常数了。
所以如果你的vector大小或者范畴已知,所以倡议在初始化的时候就规定好大小。比方初始化的时候用vector<int> v(n)
,然而留神此时size()
曾经是n
了。