vector类(一)

文章目录

  • vector介绍和使用
    • 1.vector的介绍
    • 2.vector的使用
      • 2.1 vector的定义
      • 2.2 vector iterator的使用
      • 2.3 vector空间增长问题
      • 2.4 vector增删查改
      • 2.5 vector迭代器失效问题
    • 3.vector 在OJ中的使用

vector介绍和使用

1.vector的介绍

  1. vector是表示 可变大小数组的 序列容器

  2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

  3. 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小。为了增加存储空间,其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。

  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。

  5. 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。

  6. 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好

2.vector的使用

vector学习时一定要学会查看文档:vector文档介绍,vector在实际中非常的重要,在实际中我们熟悉常

见的接口就可以,下面列出了哪些接口是要重点掌握的

在这里插入图片描述

在这里插入图片描述

2.1 vector的定义

constructor接口说明
vector()(重点)无参构造
vector(size_type n, const value_type& val = value_type())构造并初始化n个val
vector (const vector& x); (重点)拷贝构造
vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造

2.2 vector iterator的使用

iterator的使用接口说明
begin + end(重点)获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

2.3 vector空间增长问题

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize(重点)改变vector的size
reserve(重点)改变vector的capacity
  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size。

2.4 vector增删查改

vector****增删查改接口说明
push_back(重点)尾插
pop_back(重点)尾删
find查找。(注意这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[]像数组一样访问(重点)

2.5 vector迭代器失效问题

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T 。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

对于vector可能会导致其迭代器失效的操作有:

  1. 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等。
#include <iostream>
using namespace std;
#include <vector>int main()
{vector<int> v{ 1,2,3,4,5,6 };auto it = v.begin();v.resize(100, 8); // 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容v.reserve(100); // reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变v.insert(v.begin(), 0); // 插入元素期间,可能会引起扩容,而导致原空间被释放v.push_back(8);v.assign(100, 8); // 给vector重新赋值,可能会引起底层容量改变return 0;
}

以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。

解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可。

#include <iostream>
using namespace std;
#include <vector>int main()
{vector<int> v{ 1,2,3,4,5,6 };auto it = v.begin();/*v.resize(100, 8);v.reserve(100);v.insert(v.begin(), 0); v.push_back(8);v.assign(100, 8); */while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}
  1. 指定位置元素的删除操作 – erase
#include <iostream>
using namespace std;
#include <vector>int main()
{int a[] = { 1, 2, 3, 4 };vector<int> v(a, a + sizeof(a) / sizeof(int));vector<int>::iterator pos = find(v.begin(), v.end(), 3);  // 使用find查找3所在位置的iteratorv.erase(pos);  // 删除pos位置的数据,导致pos迭代器失效。cout << *pos << endl; // 此处会导致非法访问return 0;
}

在这里插入图片描述

erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效.

但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了

因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。

实例:删除vector中所有的偶数

#include <iostream>
using namespace std;
#include <vector>int main()
{vector<int> v{ 1, 2, 3, 4 };auto it = v.begin();while (it != v.end()){if (*it % 2 == 0)it = v.erase(it);else++it;}return 0;
}
  1. 注意:Linux下,g++编译器对迭代器失效的检测并不是非常严格,处理也没有vs下极端。
#include <iostream>
using namespace std;
#include <vector>// 1. 扩容之后,迭代器已经失效了,程序虽然可以运行,但是运行结果已经不对了
int main()
{vector<int> v{ 1,2,3,4,5 };for (size_t i = 0; i < v.size(); ++i)cout << v[i] << " ";cout << endl;auto it = v.begin();cout << "扩容之前,vector的容量为: " << v.capacity() << endl;// 通过reserve将底层空间设置为100,目的是为了让vector的迭代器失效 v.reserve(100);cout << "扩容之后,vector的容量为: " << v.capacity() << endl;// 经过上述reserve之后,it迭代器肯定会失效,在vs下程序就直接崩溃了,但是linux下不会// 虽然可能运行,但是输出的结果是不对的while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

vs下:

在这里插入图片描述

linux下:

在这里插入图片描述

但是在linux中, erase删除任意位置代码后,linux下迭代器并没有失效

因为空间还是原来的空间,后序元素往前搬移了,it的位置还是有效的。

#include <vector>
#include <algorithm>
int main()
{vector<int> v{ 1,2,3,4,5 };vector<int>::iterator it = find(v.begin(), v.end(), 3);v.erase(it);cout << *it << endl;while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}/*程序可以正常运行,并打印:
4
4 5 */
  1. 与vector类似,string在插入+扩容操作+erase之后,迭代器也会失效
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include <string>void TestString()
{string s("hello");auto it = s.begin();// 放开之后代码会崩溃,因为resize到20,string会进行扩容// 扩容之后,it指向之前旧空间已经被释放了,该迭代器就失效了// 后序打印时,再访问it指向的空间程序就会崩溃//s.resize(20, '!');while (it != s.end()){cout << *it;++it;}cout << endl;it = s.begin();while (it != s.end()){it = s.erase(it);// 按照下面方式写,运行时程序会崩溃,因为erase(it)之后// it位置的迭代器就失效了// s.erase(it); ++it;}
}
int main()
{TestString();return 0;
}

迭代器失效解决办法:在使用前,对迭代器重新赋值即可

3.vector 在OJ中的使用

  1. 只出现一次的数字i
class Solution {
public:int singleNumber(vector<int>& nums) {int value = 0;for (auto e : v) { value ^= e; }return value;}
};
  1. 杨辉三角OJ
// 涉及resize / operator[]
// 核心思想:找出杨辉三角的规律,发现每一行头尾都是1,中间第[j]个数等于上一行[j-1]+[j]
class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv(numRows);for (int i = 0; i < numRows; ++i){vv[i].resize(i + 1, 1);}for (int i = 2; i < numRows; ++i){for (int j = 1; j < i; ++j){vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];}}return vv;}
};

总结:通过上面的oj题目,我们发现vector常用的接口更多是插入和遍历。遍历更喜欢用数组operator[i]的形式访问,因为这样便捷。

  1. 删除排序数组中的重复项 OJ

  2. 只出现一次的数ii OJ

  3. 只出现一次的数iii OJ

  4. 数组中出现次数超过一半的数字 OJ

  5. 电话号码字母组合OJ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/775314.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《数据结构学习笔记---第五篇》---链表OJ练习上

目录 CM11链表分割 OR36 链表的回文结构 160.相交链表 141&142环形链表 CM11链表分割 step1:思路分析 1.首先可以想到&#xff0c;我们可以将原链表的元素划分到两个新的链表之中&#xff0c;由于必须保持顺序&#xff0c;所以新链表我们要用尾插。 2.为了方便进行尾插我…

自动化与智能化并行:数字化运维体系助力企业腾飞

文章目录 文章目录 文章目录 一、引言二、数字化运维体系的核心要素三、构建数字化运维体系的策略四、数字化运维体系的实施与挑战主要内容读者对象 一、引言 随着信息技术的迅猛发展&#xff0c;数字化转型已成为企业提升竞争力、实现可持续发展的必由之路。在数字化转型的过…

JSP – 支持WORD上传的富文本编辑器

1.下载示例 https://gitee.com/xproer/zyoffice-tinymce5 2.引入组件 3.配置转换接口 效果 泽优Office文档转换服务(zyOffice) 功能&#xff1a;一键导入Word转HTML&#xff0c;不装控件&#xff0c;不装Office&#xff0c;任意平台兼容(Windows,macOS,Linux,安卓Android,苹果…

【GPU系列】选择最适合的 CUDA 版本以提高系统性能

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

nvm安装以后,node -v npm 等命令提示不是内部或外部命令

因为有vue2和vue3项目多种&#xff0c;所以为了适应各类版本node,使用nvm管理多种node版本&#xff0c;但是当我按教程安装nvm以后&#xff0c;nvm安装以后&#xff0c;node -v npm 等命令提示不是内部或外部命令 首先nvm官网网址&#xff1a;https://github.com/coreybutler/…

数据结构——栈(C语言版)

前言&#xff1a; 在学习完数据结构顺序表和链表之后&#xff0c;其实我们就可以做很多事情了&#xff0c;后面的栈和队列&#xff0c;其实就是对前面的顺序表和链表的灵活运用&#xff0c;今天我们就来学习一下栈的原理和应用。 准备工作&#xff1a;本人习惯将文件放在test.c…

[C++]深入解析:如何计算C++类或结构体的大小

目录 什么是内存对齐 类的成员的存储规则 怎么进行内存对齐&#xff08;介绍规则与例子讲解&#xff09; 什么是内存对齐 内存对齐是指将数据存储在内存中时&#xff0c;按照一定的规则让数据排列在规定的地址上&#xff0c;以提高数据访问的效率和速度。在C中&#xff0c;结…

鸿蒙OS开发问题:(ArkTS)【 RSA加解密,解决中文乱码等现象】

RSA加解密开始构建工具类就是举步维艰&#xff0c;官方文档虽然很全&#xff0c;但是还是有很多小瑕疵&#xff0c;在自己经过几天的时间&#xff0c;彻底解决了中文乱码的问题、分段加密的问题。 首先看官方示例代码(以RSA非对称加解密&#xff08;多次调用doFinal实现分段&a…

TikTok养号怎么做?打破0播放的前提是做好这些

TikTok养号的重要性不必多少&#xff0c;不仅可以在创号初期保障账号安全&#xff0c;后期的账号流量也需要以前期养好账号为前提。下面就给大家分享如何养号的真实操作攻略&#xff01; 一、为什么要养号 &#xff08;1&#xff09;提高系统推荐精准度 系统不了解新账户人设…

spring boot 生成PDF模板文件

1、主要目录 2、maven依赖 <!--工具类依赖--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.19</version></dependency><dependency><groupId>com.alibaba&l…

56. 合并区间(力扣LeetCode)

文章目录 56. 合并区间题目描述思路贪心算法方法一&#xff1a;直接在res中修改代码逻辑梳理&#xff1a; 方法二&#xff1a;在原数组中插入一个超出题目范围的数组代码逻辑梳理&#xff1a; 56. 合并区间 题目描述 以数组 intervals 表示若干个区间的集合&#xff0c;其中单…

律甲法务OA平台:信鸥科技引领法律行业新篇章

随着信息技术的飞速发展&#xff0c;法律行业也迎来了数字化转型的重要时刻。在这个信息化、智能化的时代&#xff0c;如何运用科技手段提升法律服务的质量和效率&#xff0c;成为法律行业亟待解决的问题。信鸥科技&#xff0c;作为业界的佼佼者&#xff0c;凭借其深厚的技术积…

Kafka详细教程(一)

总体目录 1、什么是消息队列 消息队列&#xff0c;英文名&#xff1a;Message Queue&#xff0c;经常缩写为MQ。从字面上来理解&#xff0c;消息队列是一种用来存储消息的队列 。来看一下下面的代码 // 1.创建一个保存字符串的队列Queue<String> queue new LinkedList&…

使用patchelf解决vscode远程连接不支持低版本glibc的问题

使用patchelf解决vscode远程连接不支持低版本glibc的问题 目录 使用patchelf解决vscode远程连接不支持低版本glibc的问题1. 动态链接库下载2. 用 patchelf 修改 vscode-server 依赖的 glibc 版本 VScode 1.86 版本的 remote 要求 glibc 2.28 及以上&#xff0c;于是在各种旧版本…

基于RK3588多can口多串口机器人全功能板

RK3588机器人控制器有五大技术优势 1. 内置多种功能强大的嵌入式硬件引擎&#xff0c;支持8K60fps 的 H.265 和 VP9 解码器、8K30fps 的 H.264 解码器和 4K60fps 的 AV1 解码器&#xff1b;支持 8K30fps 的 H.264 和H.265 编码器&#xff0c;高质量的 JPEG 编码器/解码器&…

不显示excel中零值方法

excel中想让数字0不显示的方法如下&#xff1a; √去掉则数字格式0不再显示 。若找不到此项&#xff0c;运行以下代码即可&#xff1a; Sub 去除excel中零值() ActiveWindow.DisplayZeros False 不显示零值 End Sub altf11打开vba idea&#xff0c;插入->模块&#xff…

UniRepLKNet:一种用于音频、视频、点云、时间序列和图像识别的通用感知大核卷积神经网络

论文: https://arxiv.org/abs/2311.15599 模型: https://huggingface.co/DingXiaoH/UniRepLKNet/tree/main 主页&#xff1a;https://invictus717.github.io/UniRepLKNet/ contribution 提出了四条guide line用于设计大核CNN架构模型&#xff0c;用于图像识别&#xff0c;语…

elementui日期时间选择框自定义组件

1.需求场景 业务中需要&#xff0c;日期选择框方便客户对日期的选择&#xff08;比如近5天&#xff0c;本周&#xff0c;本月&#xff0c;本年等等&#xff09;&#xff0c;并按小时展示。 2.组件代码MyDateTimeChange.vue <template><el-date-pickerv-model"…

鸿蒙开发之ArkUI组件常用组件图片和文本

ArkUI即方舟开发框架是HarmonyOS应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能&#xff08;组件、布局、动画以及交互事件&#xff09;&#xff0c;以及实时界面预览工具等&#xff0c;可以支持开发者进行可视化界面开发。 开发文档地址 &…

国赛大纲解读

1. 第一部分,是针对5G基础知识的掌握,第二部分是人工智能基本算法的掌握,就是人工智能的应用,用5G+人工智能(AI算法)进行网络优化的问题,要有网络优化的基础知识,比如说:某个区域的覆盖问题,覆盖特别差,但有数据,覆盖电频,srp值这些数据给你,根据数据来判断是…