关于c++:CSTL教程1vector容器是什么实用教程来啦超简单易懂拿来就用

3次阅读

共计 2821 个字符,预计需要花费 8 分钟才能阅读完成。

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 int
for(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() = 3
for(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,大小变为 0
void erase(iter l, iter r)清空迭代器指向的区间 $[l, r)$ 的元素。

v.pop_back();
//5 5 5 1 2
v.clear();
//null

其余的个别也用不着。

判断是否为空

bool empty()判断 vector 是否为空

vector<int> a(3);
//v.empty() == false
a.clear();
//v.empty() == true

一些罕用函数(以下 v 指实例对象)

v.resize(n)将 vector 大小批改为 n
v.begin()获取 vector 第一个元素的迭代器(指针)
v.end()获取 vector 最初一个元素的后一个地位的迭代器
v.rbegin() 获取 vector 倒数第一个元素的迭代器(指针)
v.rend()获取 vector 倒数最初一个元素的后一个地位的迭代器

vector<int> v = {1, 2, 3}
cout << *v.begin() << '\n';//1
cout << *v.rbegin() << '\n';//3
cout << *(++ 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 了。

正文完
 0