前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >刷题、找工作,学C++不会STL怎么行?vector篇(下)

刷题、找工作,学C++不会STL怎么行?vector篇(下)

作者头像
TechFlow-承志
发布2022-08-26 16:14:28
2380
发布2022-08-26 16:14:28
举报
文章被收录于专栏:TechFlowTechFlow

作者 | 梁唐

大家好,我是梁唐。

昨天介绍了vector的相关原理,我们今天接着来聊vector,今天来聊聊它的使用。

我们还是按照惯例,由浅入深。

基础操作

首先是一些最基础的操作。

代码语言:javascript
复制
#include<vector> // 头文件
vector<T> vec; // 创建vector对象
vec.push_back(T{}); // 向vector尾部插入数字
cout<<vec[0]<<endl; // 通过下标访问元素

vector最基础的操作就只有这四条语句,也是使用得最多的四条。

我们一条一条来说,include没的说,引入vector的包,也是使用vector的基础。

第二条是创建一个vector的对象,vector支持多种构造函数,这个只是其中最简单的一种,即默认构造函数。vector支持泛型,我们可以自定义我们需要的类型,我们甚至还可以定义一个元素是vector的vector,即二维vector,如:vector<vector<int>>

第三条是插入语句,vector是一个可变长度的数组,我们可以使用push_back操作往数组的末尾插入元素。只有往数组的末尾插入元素才能保证这个插入操作是

O(1)

的。当然因为插入可能会引起vector重新分配内存,所以实际上push_back的复杂度并不是

O(1)

,不过我们使用的时候可以忽略这其中的细微区别,就当做是

O(1)

即可。

第四条是vector中的元素访问,vector创建之后我们完全可以当做是数组一样通过下标来访问,vector中的下标也是从0开始的。

很长一段时间内我都是用这4条语句打比赛的,作为入门已经够用了。当然作为学习者来说,我们不能追求一知半解,关于vector也有很多更高端的用法。

进阶用法

下面介绍一些进阶用法。

首先是构造函数,我们有了更多的选择,我简单列举一下:

代码语言:javascript
复制
vector(int nSize);
vector(int nSize, const t &t);
vector(const vector&);
vector(begin, end);

我们一条一条来说,第一条是在创建vector时传入一个整数n,初始化一个长度为n的vector。如:vector<int> vec(10);

但是这样有一个问题是我们创建出来的vector当中的数据是脏数据,我们不知道里面的值是多少。如果希望创建vector的时候还能够将其中的元素指定为自己想要的值,可以使用第二条命令。也就是我们既传入长度,也传入一个我们用来初始化的值,这样初始化之后得到的vector当中的所有元素都是我们传入的t。

第三条和第四条都是拷贝构造函数,也即拷贝其他的vector,得到新的vector。

然后是一些其他的函数:

代码语言:javascript
复制
vec.pop_back();
vec.clear();
vec.empty();
vec.size();
vec.begin();
vec.end();

首先是pop_back

pop_backpush_back是相反的操作,它会从末尾弹出一个元素。也就是说vector的长度不仅可以增长,也可以变短,删除多余的我们不需要的数据。另外使用pop_back,我们也可以实现一些特殊的数据结构,比如栈。

第二个常用的是clear,即清除vector中所有数据。

第三个是empty,用来判断vector是否为空。

第四个是size,它会返回vector当前的元素个数。

最后是beginend这两个函数,它们会分别返回vector的头尾位置,这里要注意end返回的是最后一个元素的后一个位置,可以理解成一个左闭右开的区间的左右端点。

很多同学会很疑惑,我要知道vector的左右端点有什么用?其实用处很大,因为C++当中很多的内置函数接收的参数就是数组的起始位置,比如说最常用的排序函数sort,它接受的就是一个数组的头尾位置。如果我们的vector是int或者是float类型,那么就可以直接调用sort函数对数组中元素进行排序。

代码语言:javascript
复制
#include<algorithm>

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

只要这一行语句就实现了排序操作,算法内置了快速排序,我们就不需要自己实现了。

关于sort函数的使用我们之后会在写一篇文章好好聊聊,今天就只是一笔带过提一下。

迭代器

最后我们来看看vector另外一个非常内容——迭代器。

迭代器严格说起来是一种设计模式,可以在不暴露对象内部实现的情况下访问对象中的内部元素。比如说我们通过迭代器访问一个数据结构,我们不需要关心这个数据结构内部的实现,它究竟是一棵树还是一个线性表,是二叉树还是多叉树,我们只需要按照规定的顺序迭代访问即可。

如果不使用迭代器想要遍历数据结构,就必然需要对数据结构的实现方式有所了解,也就有了某种意义上的耦合。

说起来玄乎其玄,其实迭代器的使用非常简单,和指针有些类似我们可以通过自增和自减操作来前后移动迭代器。

首先我们来看一个例子:

代码语言:javascript
复制
vector<int> vec(10, 4);
for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
    cout<<*it<<endl;
}

短短几行代码就已经表明了迭代器的创建和使用,首先创建的时候我们通过vector的类型加上::iterator来表明我们创建的迭代器类型。迭代器默认从头指针移动向尾指针,也就是从begin移动向end,每次自增表示移动了一位 。

如果我们要反向移动也可以,vector也提供了反向的begin和end,叫做rbeginrend

有了迭代器除了可以访问vector中的元素之外,还可以调用一些迭代器函数实现一些特有的功能。比如说inserterase函数,大家都看得出来可以插入或者删除一个元素。

代码语言:javascript
复制
vector<int> vec(10, 10);
vector<int>::iterator it = vec.begin();

vec.insert(it, 10); // 往it之前插入10
vec.erase(it); // 删除it位置的值

除此之外还可以批量插入以及批量删除,只不过用的频率不高,我就不展开细讲了,感兴趣的同学可以自行百度一下。

说起来vector很简单,但是细讲下来内容还是不少的。不知道大家有没有发现一点,在计算机领域当中很多知识都是耦合的,你想要把这个东西理解透往往需要先了解另外的知识。有一个小知识点没理解呢,可能会导致一大片的知识盲区。

比如这里你想要理解透vector的使用,需要了解迭代器,而了解迭代器呢,你可能又需要先搞清楚设计模式,以及指针。如果你对指针就一头雾水的话,那么设计模式、迭代器以及指针相关的一系列内容都无法掌握。

正因为计算机系统内的知识有这样的耦合性,所以需要我们在学习的时候深入理解、深入思考,尤其是一些基础内容,尽量不留下知识盲区,否则会给以后的学习带来巨大的麻烦。

好了,今天的内容就到这里,感谢大家的阅读。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基础操作
  • 进阶用法
  • 迭代器
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档