【C++】详解vector二维数组的全部操作(超细图例解析!!!)

目录

一、前言

二、 深度理解vector 的二维数组(重点!)

 三、vector 二维数组的空间理解(重点!)

✨问题分析

✨如何合理定制vector的内存空间

 四、vector 二维数组的初始化

五、vector 二维数组的 添加与删除

✨添加一行

✨添加一列

✨删除一行

✨删除一列

六、常考面试题

 七、共勉


一、前言

    最近在刷 Leetcode 的时候,发现 vector 的二维数组操作 都还没弄明白吗,但是STL的强大是众所周知滴,早晚都是要解决滴,因此专门写下这篇文章,以供自己复习和各位老铁使用,快速的回忆vector的用法,让你找回自信,不用再竞赛的时候颜面尽失。
    vector 的一维操作可以看看之前这篇文章哦:vector 详解

二、 深度理解vector 的二维数组(重点!)

     在解决大部分算法问题的时候,通常都会遇到二维数组 vector<vector<int>> table, 但是不知道怎么对其进行初始化(初始化时指定二维容器的大小),于是通过查阅了很多资料,将其总结如下:

vector<vector<int>> table(size1, vector<int>(size2, 0));

 代码说明:声明一个名为 table 的容器,其元素为 vector的容器。简单来说类似一个int型的二维数组。

这样,就得到了一个如下图所示的二维容器。 

 具体代码的内容,可以这样理解:

 图中,我将外围容器table的初始化参数分成了两部分 A、B 

  • A: table外围容器的大小
  • B: table外围容器的内容,即 size1个vector型的元素。
  • B1:内部容器的大小
  • B2:内部容器的内容

观察规律,可以得出如下的初始化格式:容器(大小,内容)

 三、vector 二维数组的空间理解(重点!)

      我们都知道,在 C语言 中,创建一维数组或者更高维度的数组时,都是需要提前给他分配大小的。
      而在 C++的 vector 容器 中我们并不需要那么做,我们可以直接push进去后,根据下标访问它,如:

 ✨问题分析

	vector<int> a;a.push_back(1);cout << a[0];

 由此处诞生出了两个问题

  1.  在处理小数据是没问题的,但处理大数据时,vector 会重新分配内存,一般会把容量(所分配好的内存空间)翻倍,这将导致出现大量的冗余空间。
  2. 在对二维的数组创建时,会出现创造失败的情况,如下面的情况就会报错:
vector<vector<int>> a;  // 创建一个空的二维向量a
a[0].push_back(1);       // 尝试访问a的第一个元素(即空向量),然后在其上调用push_back()方法,但是a目前为空,没有索引为0的元素,因此这将导致访问越界错误。
cout << a[0][0];         // 试图输出a的第一个元素的第一个元素,但是由于a为空,这也会导致访问越界错误。

错误原因: 

  1. 尝试访问 a 的第一个元素(即空向量),然后在其上调用push_back()方法,但是a目前为空,没有索引为 0 的元素,因此这将导致访问越界错误。
  2.  试图输出 a 的第一个元素的第一个元素,但是由于a为空,这也会导致访问越界错误。

✨如何合理定制vector的内存空间

首先要明白,我们第二个问题的出现,其实就是因为第一个问题,那么我们逐个分析一下:

  • 对于 vector 的 .size() 代表查询它的 动态数组vector中有多少个有效数。
  • 对于 vector 的.capacity()代表查询它的容量(最多放多少个数)。

 如何理解这两个函数接口呢?

  • resize(Container::size_type n)强制把容器改为容纳n个元素。调用resize之后,size将会返回n。如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果n大于当前容量,在元素加入之前会发生重新分配。
  • reserve(Container::size_type n)强制容器把它的容量改为至少n,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。(如果n小于当前容量,vector忽略它,这个调用什么都不做,string可能把它的容量减少为size()和n中大的数,但string的大小没有改变。

 【总结】上述两方法的区别

  1. reserve表示容器预留空间,但并不是真正的创建对象,需要通过insert()或push_back()等创建对象resizee既分配了空间,也创建了对象
  2. reserve只修改capacity大小,不修改size大小,resize既修改capacity大小,也修改size大小。
  3. resize带两个参数,一个表示容器大小,一个表示初始值(默认为0)。reserve只带一个参数,表示容器预留的大小。
  4. 因此,我们在对一维数组push前,可以来一个reverse,这样在不断push的过程中就不会发生重新分配了。如:vector<int> a; a.reserve(1000);

所以针对问题二出现的原因:vector 直接根据下标访问必须要先push,存在数才行。而上面的代码想直接对第一行里面的各个元素进行访问或者修改时绝对不行的。但是相反,如果我们先对第一行进行赋值,然后再访问,这样又是可以的,如:

vector<vector<int>> a;
a.push_back(vector<int>()); // 添加一个空的一维向量
a[0].push_back(1);          // 现在可以向a的第一个元素(现在是一个向量)添加元素了
cout << a[0][0];            // 输出1

 因此,想要直接对第一行第一列的进行调整,就需要我们预先给他点空间了!!

 四、vector 二维数组的初始化

首先,要先知道:二维 vector 如何获得行数和列数。

vector<vector<int>> a(r, vector<int>(c));
int row = a.size();          //获取行数
int column = a[0].size();    //获取列数

 方法一:定义时,直接初始化
(1)下面定义的是行为r,列为c的二维数组

vector<vector<int>> ans(r, vector<int>(c));

(2)下面定义的是行为r,列为c的二维数组,初始值为0

vector< vector<int> > a(r, vector<int>(c, 0)); 

方法二:用resize来提前构建

(下面定义的是行为r,列为c的二维数组,初始值为0–因为resize默认为0)

vector<vector<int>> new_mat(r);//注意这个r是不可缺少的,规定其有多少行
for(int i=0 ;i<r; i++) //二维vector的初始化时有要求的
{new_mat[i].resize(c);
}

方法三:每行不一定几个数,就是想对每行的列进行操作

vector<vector<int>>mat(r);//每行的定义
mat[i].push_back(1);//这就是该第i-1行的插入一个元素,值为1

 

五、vector 二维数组的 添加与删除

✨添加一行

//插入一行数组:将in_row数组插入到第2行! 
vector<int> in_row(5,6);//初始化一个数组,包含5个元素并且全为6
a.insert(a.begin()+2,in_row);

✨添加一列

for(int i=0;i<a.size();i++)
{a[i].insert(a[i].begin()+2,9);
}

✨删除一行

a.erase(a.begin() + 2, a.begin() + 3);

✨删除一列

//删除a的第二列for (int i = 0; i < a.size(); i++){a[i].erase(a[i].begin() + 2, a[i].begin() + 3);}

六、常考面试题

题目:杨辉三角形
链接:118. 杨辉三角

class Solution {
public:vector<vector<int>> generate(int numRows) {// 生成一个二维数组vector<vector<int>> vv;// 给二维数组开辟有效空间---开辟numRows行vv.resize(numRows);for(int i = 0;i<numRows;i++){//每一行开辟i+1个 空间,并且进行初始化为 0 vv[i].resize(i+1,0);//每一行的第一个和最后一个为 1vv[i].front() = vv[i].back() = 1;}// 每一次都从第3行开始,第二个开始遍历for(int i = 2;i<numRows;i++){for(int j = 1;j<i;j++){vv[i][j] = vv[i-1][j-1] + vv[i-1][j];}}return vv;}
};

 七、共勉

 以下就是我对【C++ STL】vector 二维数组 的理解,如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对C++STL库的理解,请持续关注我哦!!!

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

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

相关文章

性能优化 - 你能说一说,为什么做了骨架屏,FCP的指标还是没有提升吗

难度级别:中高级及以上 提问概率:80% FCP的全程是First Contentful Paint,是衡量网页性能的一个重要指标,很多人把FCP理解为元素内容首次渲染到浏览器上的时间。但由于现在比较流行的Vue或是React项目中,HTML文档最初只有一个id为app的DIV…

自建ceph存储集群方案之从零到一

概述 根据硬件摩尔定律&#xff0c;硬件成本随时间越来越低&#xff0c;性能较之前越来越高&#xff0c;尤其是随着pcie全闪灯普及&#xff0c;理论上作为云服务的基础设施&#xff0c;存储应该越来越便宜。然而&#xff0c;购置商用sds产品的成本却一直居高不下&#xff0c;越…

在unbuntu服务器上使用nginx+uwsgi部署django项目

一、配置nginx 1. 安装nginx apt-get install nginx2. 编写nginx配置文件 进入nginx.conf文件路径&#xff1a;/etc/nginx/nginx.conf 编写以下内容&#xff1a; events {worker_connections 1024; # 工作进程的最大连接数量 }http{include mime.types;# 日志格式及保存路径…

(译) 理解 Elixir 中的宏 Macro, 第五部分:组装 AST

Elixir Macros 系列文章译文 [1] (译) Understanding Elixir Macros, Part 1 Basics[2] (译) Understanding Elixir Macros, Part 2 - Macro Theory[3] (译) Understanding Elixir Macros, Part 3 - Getting into the AST[4] (译) Understanding Elixir Macros, Part 4 - Divin…

【Labview】虚拟仪器技术

一、背景知识 1.1 虚拟仪器的定义、组成和应用 虚拟仪器的特点 虚拟仪器的突出特征为“硬件功能软件化”&#xff0c;虚拟仪器是在计算机上显示仪器面板&#xff0c;将硬件电路完成信号调理和处理功能由计算机程序完成。 虚拟仪器的组成 硬件软件 硬件是基础&#xff0c;负责将…

数字化转型回归底层逻辑

2024年第一季度已然过去&#xff0c;对于我们每个人而言&#xff0c;这都是一次严峻的挑战。2015年&#xff0c;蚓链数字化营销系统踏上研发之路。让我们回顾数字技术对企业的影响阶段&#xff1a;2012-2015 年&#xff0c;互联网在消费端产生巨大影响&#xff0c;引发了虚拟经…

清空nginx缓存并强制刷新

当对nginx的文件进行修改或更新时&#xff0c;可能会出现旧文件被缓存而无法立即生效的问题&#xff0c;此时需要清空nginx的文件缓存并强制刷新。可以通过以下步骤实现&#xff1a; 登录nginx服务器执行命令&#xff1a;sudo nginx -s reload &#xff08;重新加载nginx配置&…

YOLOv5改进--轻量化YOLOv5s模型

文章目录 1、前言2、轻量化模型结构&#xff1a;3、模型对比4、训练结果图5、目标检测文章 1、前言 在边缘设备的场景下&#xff0c;目前的YOLOv5s&#xff0c;虽然能够快速实现目标检测&#xff0c;但是运行速度依旧稍慢点&#xff0c;本文在牺牲一点精度前提下&#xff0c;提…

Web漏洞-文件上传常见验证

后缀名&#xff1a;类型&#xff0c;文件头等 后缀名&#xff1a;黑白名单 文件类型&#xff1a;MIME信息 文件头&#xff1a;内容头信息 常见黑名单&#xff08;明确不允许上传的格式后缀&#xff09;&#xff1a;asp、php、jsp、aspx、cgi、war &#xff08;如果没有完整…

vscode:插件开发

文档&#xff1a; 连接 终端执行 sudo pnpm install -g yo generator-codeyo code// 这里建议选择 JavaScript 很少出错 # ? What type of extension do you want to create? New Extension (JavaScript) # ? Whats the name of your extension? HelloWorld ### Press <…

nacos derby.log无法的读取+derby数据库启动失败分析解决

排查思路分析 日志报错&#xff1a; derby.log文件权限不够&#xff08;root权限&#xff09;&#xff0c;无法读取&#xff0c;我用普通用户启动。 使用命令chown xx:xx derby.log修改属主和属组为普通用户后&#xff0c;又报出其他错误。 数据库启动不了&#xff0c;无…

Composer Windows 安装

Composer 的下载地址为&#xff1a;Composer 1 运行安装程序 当启动安装程序后单击下一步继续。 选择 PHP 路径 如果你的计算机上没有安装 PHP 的话&#xff0c;Composer 的安装无法继续。 你需要选择你本地安装的 PHP 路径。 配置代理地址 默认的情况下&#xff0c;可以不…

【LeetCode刷题记录】15. 三数之和

15 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [ n u m s [ i ] , n u m s [ j ] , n u m s [ k ] ] [nums[i], nums[j], nums[k]] [nums[i],nums[j],nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 n u m s [ i ] n u m s [ j ] n u …

java基础语法(11)| 内部类

1. 内部类 1.1 什么是内部类 将一个类A定义在另一个类B里面&#xff0c;里面的那个类A就称为内部类&#xff0c;B则称为外部类。 1.2 内部类的分类 成员内部类 局部内部类 匿名内部类 1.3 成员内部类 在描述事物时&#xff0c;若一个事物内部还包含其他事物&#xff0c;就…

基于starganvc2的变声器论文原理解读

数据与代码见文末 论文地址&#xff1a;https://arxiv.org/pdf/1907.12279.pdf 1.概述 什么是变声器&#xff0c;变声器就是将语音特征进行转换&#xff0c;而语音内容不改变 那么我们如何构建一个变声器呢&#xff1f; 首先&#xff0c;我们肯定不能为转换的每一种风格的声…

JavaEE初阶——多线程(一)

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享多线程的第一部分:引入线程以及创建多线程的几种方式 此文章是建立在前一篇文章进程的基础上的 如果有不足的或者错误的请您指出! 1.认识线程 我们知道现代的cpu大多都是多核心…

【Figma】安装指南及基础操作

先前做UI设计一直都是用PS等绘图软件设计&#xff0c;但发现在纠结像素和排版问题上会花很多时间&#xff0c;再加上AI没来得及上手&#xff0c;就需要迅速出成图&#xff0c;此时通过论坛发现了figma&#xff0c;基本上可以满足足够的需求&#xff0c;并且可以在windows系统上…

【云开发笔记NO.27】分布式数据库

在云原生开发中&#xff0c;分布式数据库是一种特殊类型的数据库管理系统&#xff0c;其数据不是存储在单个集中的服务器上&#xff0c;而是分散在网络中的多个节点或服务器上。这种分散存储的方式使得分布式数据库具有很高的可扩展性、容错性和性能优势。云原生环境下的分布式…

SVG图标显示

SVG图标显示 1.安装SharpVectors.Wpf包 2.添加引用 xmlns:svgc"http://sharpvectors.codeplex.com/svgc/"3.加载svg文件&#xff0c;生成操作选择资源(Resource) 4.UI界面显示SVG图像 <Button Click"OnSaveFileClick" ToolTip"Save Svg File…

武汉星起航:跨境电商领域崭露头角,以实战经验引领行业新潮流

随着全球经济的演进&#xff0c;跨境电商正成为国际贸易的引擎&#xff0c;而武汉星起航电子商务有限公司凭借其丰富实战经验和专业团队&#xff0c;在这一领域取得了引人瞩目的成绩。公司成立于2020年&#xff0c;自2017年起紧紧围绕亚马逊自营店铺&#xff0c;致力于为合作伙…