C++---vector容器

是STL容器中的一种常用的容器,由于其大小(size)可变,常用于数组大小不可知的情况下来替代数组。vector容器与数组十分相似,被称为动态数组。时间复杂度为O(1)。

数组数据通常存储在栈中,vector数据通常存储在堆中。

动态扩展不是在原空间后加入空间,而是寻找更大空间,将数据拷贝新空间,释放新空间。

头文件:#include <vector>

迭代器类似于指针,提供了对象的间接访问,但获取迭代器并不是使用取地址符。如果将指针理解为元素的“地址”,那么迭代器可以理解为元素的“位置”。可以使用迭代器访问某个元素,迭代器也能从一个元素移动到另一个元素。

一个迭代器的范围由一对迭代器表示,分别为 begin 和 end。其中 begin 成员返回指向第一个元素的迭代器;end 成员返回容器最后一个元素的下一个位置(one past the end),也就是指向一个根本不存在的尾后位置。

vector初始化

vector<T> v1                    创建一个名为v1是元素类型为T的空vector

vector<int> v2 (n):            创建一个vector,元素类型为int,元素个数为n,值默认为0

vector<int> v3 {1,2,3,4,5}  vector有5个数,注意花括号

vector<int>v4 (4,1)            vector由4个值为1组成

vector<int>v5 (v4)             将v4所有值复制到v5中

vector<int>v6(v3.begin(), v3.end())  将v3的值从头到尾复制到v6

vector<int>v7(v3.rbegin(), v3.rend()) 将v3的值从尾到头复制到v7

cbegin    和begin()功能相同,在其基础上增加了 const 属性,不能用于修改元素。
cend       和end()功能相同,在其基础上增加了 const 属性,不能用于修改元素。
crbegin   和rbegin()功能相同,在其基础上增加了 const 属性,不能用于修改元素。
crend      和rend()功能相同,在其基础上增加了 const 属性,不能用于修改元素。

vector方法

v2.empty() 判断v2是否为空,为空返回true,否则返回false

v2不为空,返回3

if(v2.empty()) {return 2;
}else{return 3;
}

元素长度

v2.size() 返回实际v2中的元素个数

int len = v2.size();

v2.capacity()返回v2中可以容纳的元素个数

区分:capacity 当前vector分配的大小,size 当前使用数据的大小

v2.resize()改变v2中的实际元素个数

v2.reserve()增加v2 的容量

访问元素

operator[] 用于从vector中访问指定元素,它接受一个索引并返回指定位置元素的引用。语法:

 vector::operator[size_type n];

例如:v2[n] 是v2第n个位置元素的引用,不能用于下标操作添加元素,像v2[7]=5是错的。vector容器的下标也是从0开始计数的

vector.at(i)等同于vector[i],访问数组下表的元素,例如:v2.at(2) 返回下标为2的值的元素

两者区别:虽然两者访问元素都不能越界,但是operator不做边界检查,哪怕越界也会返回一个引用(错误的),at会做边界检查,如果越界,会抛出std::out_of_range异常。

cout<<v2[3]<<endl;
cout<<v2.at(3)<<eendl;

v2.front()返回第一个元素

v2.back()返回最后一个元素

v2.data()返回v2第一个元素的指针

元素排序

sort 需要头文件 #include <algorithm>

sort(v2.begin(), v2.end())一种是两个参数,一般为升序(由小到大)

sort(v2.begin(), v2.end(), t),是三个参数,第三个参数可以写排序规则,一般搭配lambda表达式的捕获列表使用

vector<int> a{0,10,9,8,1,5,2,3,6,4,7};
bool cmp(int x,int y){return x>y;}
sort(a.begin(), a.end(),cmp);
//两者等价
sort(a.begin(), a.end(),[](int x, int y){return x > y;});
//原有形式,省略是因为C++可以自动识别函数返回值得数据类型
sort(a.begin(), a.end(),[](int x,int y) -> bool {return x>y;} );

reverse(v2.begin(), v2.end()) 逆序输出

reverse(a.begin(), a.end());  // 原位逆序排列
//结果
7 4 ....9 10 0

unique(v2.begin(), v2.end())将输入序列相邻的重复项“消除”,一般搭配sort使用,先排序后消除。

例如,0 0 0 0 3 5 输出后 0 3 5

交换元素

v2.swap() 交换v2 其中的两个元素的所有内容

swap() 函数在头文件 <algorithm> 和 <utility> 中都有定义,使用时引入其中一个即可。

v2.assign() 用新元素替换所有内容

添加元素

向 vector 容器中添加元素的唯一方式就是使用它的成员函数,如果不调用成员函数,非成员函数既不能添加也不能删除元素。

v3.push_back(v) 在v3尾端添加一个值为v的元素

v3.push_back(5);
cout<<v3<<endl;
//结果 1,2,3,4,5,5

v2.emplace_back()  在尾部添加一个元素

    vector<int> values{};values.emplace_back(1);values.emplace_back(2);for (int i = 0; i < values.size(); i++) {cout << values[i] << " ";}//结果1 2

两者区别在于底层实现的机制不同。push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。

插入元素

v2.insert(pos,elem)在迭代器 pos 指定的位置之前插入一个新元素elem

iterator insert(pos,n,elem)在迭代器 pos 指定的位置之前插入 n 个元素 elem,并返回表示第一个新插入元素位置的迭代器。
iterator insert(pos,first,last) 在迭代器 pos 指定的位置之前,插入其他容器(不仅限于vector)中位于 [first,last) 区域的所有元素,并返回表示第一个新插入元素位置的迭代器。
iterator insert(pos,initlist)在迭代器 pos 指定的位置之前,插入初始化列表(用大括号{}括起来的多个元素,中间有逗号隔开)中所有的元素,并返回表示第一个新插入元素位置的迭代器。

插入有很多种形式

vector<int> demo{1,2};
//第一种格式用法
demo.insert(demo.begin() + 1, 3);//{1,3,2}
//第二种格式用法
demo.insert(demo.end(), 2, 5);//{1,3,2,5,5}
//可以看出end指的不是数组最后一位,而是最后一位的下一个位置
//第三种格式用法
array<int,3>test{ 7,8,9 };
demo.insert(demo.end(), test.begin(), test.end());//{1,3,2,5,5,7,8,9}
//第四种格式用法
demo.insert(demo.end(), { 10,11 });//{1,3,2,5,5,7,8,9,10,11}

v2.emplace()  指定位置前插入一个新元素,emplace() 每次只能插入一个元素,而不是多个。

vector<int> demo1{1,2};
//emplace() 每次只能插入一个 int 类型元素
demo1.emplace(demo1.begin(), 3);
for (int i = 0; i < demo1.size(); i++) {cout << demo1[i] << " ";
}
//结果 3 1 2

emplace与insert比较,emplace效率更高,因为,insert需要将新元素将其生成,再将其拷贝或复制到容器中,emplace是直接在容器指定位置构造元素。

删除元素

v3.pop_back();
//结果 从1 2 3 4 5 5 变为1 2 3 4 5
vector<int>demo{ 1,2,3,4,5 };
auto iter = demo.erase(demo.begin() + 1);//删除元素 2
for (int i = 0; i < demo.size(); i++) {cout << demo[i] << " ";
}
//iter迭代器指向元素 3
cout << endl << *iter << endl;//结果
1 3 4 5
3
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;int main()
{vector<int>demo{ 1,2,3,4,5 };//交换要删除元素和最后一个元素的位置swap(*(std::begin(demo)+1),*(std::end(demo)-1));//等同于 swap(demo[1],demo[4])//交换位置后的demo容器for (int i = 0; i < demo.size(); i++) {cout << demo[i] << " ";}demo.pop_back();cout << endl << "size is :" << demo.size() << endl;cout << "capacity is :" << demo.capacity() << endl;//输出demo 容器中剩余的元素for (int i = 0; i < demo.size(); i++) {cout << demo[i] << " ";}return 0;
}
//结果
1 5 3 4 2
size is :4
capacity is :5
1 5 3 4
vector<int> demo{ 1,2,3,4,5 };
//删除 2、3
auto iter = demo.erase(demo.begin()+1, demo.end() - 2);
for (int i = 0; i < demo.size(); i++) {cout << demo[i] << " ";
}//结果
1 4 5
vector<int>demo{ 1,3,3,4,3,5 };
//交换要删除元素和最后一个元素的位置
auto iter = remove(demo.begin(), demo.end(), 3);
//输出剩余的元素
for (auto first = demo.begin(); first < iter;++first) {cout << *first << " ";
}
//结果
1 4 5
长度仍为6

注意,在对容器执行完 remove() 函数之后,由于该函数并没有改变容器原来的大小和容量,因此无法使用之前的方法遍历容器,而是需要向程序中那样,借助 remove() 返回的迭代器完成正确的遍历。

remove() 的实现原理是,在遍历容器中的元素时,一旦遇到目标元素,就做上标记,然后继续遍历,直到找到一个非目标元素,即用此元素将最先做标记的位置覆盖掉,同时将此非目标元素所在的位置也做上标记,等待找到新的非目标元素将其覆盖。因此,demo为1 3 3 4 3 5,删除3,得到的结果为 1 4 5 4 3 5

过程:3做标记,3再做标记,4覆盖第一个3,做标记,3再做标记,5覆盖第二个3,做标记。

所以,可以使用 erase() 成员函数删掉这些 "无用" 的元素。

    vector<int>demo{ 1,3,3,4,3,5 };//交换要删除元素和最后一个元素的位置auto iter = remove(demo.begin(), demo.end(), 3);demo.erase(iter, demo.end());//输出剩余的元素for (int i = 0; i < demo.size();i++) {cout << demo[i] << " ";}
//结果 1 4 5
长度变为3
    vector<int>demo{ 1,3,3,4,3,5 };//交换要删除元素和最后一个元素的位置demo.clear();cout << "size is :" << demo.size() << endl;cout << "capacity is :" << demo.capacity() << endl;
//结果
size is :0
capacity is :6

二维数组

完整版:vector<vector<int>> table(size1, vector<int>(size2, 0)); 行列都给了

        名为table的vector容器包含元素为vector的容器。列为size2,行为size1,值为0。

省略版:vector<vector<int>> table; 行列未知

               vector<vector<int>> table(5); 行为5,也就是长度

获取二维数组长度

int size_row = table.size();  //获取行数
int size_col = table[0].size();  //获取列数

访问二维数组

for (int i = 0; i < a.size(); i++)
{for (int j = 0; j < a[0].size(); j++)//注意如果arr为空不可直接arr[0]{cout << a[i][j] << endl;}
}

https://blog.csdn.net/aruewds/article/details/117375364

C++ STL vector插入元素(insert()和emplace())详解 (biancheng.net)

http://t.csdnimg.cn/Ej3rl

http://t.csdnimg.cn/ebFXf

使用lambda表达式实现sort的自定义排序 - octal_zhihao - 博客园 (cnblogs.com)

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

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

相关文章

napi系列学习进阶篇——NAPI生命周期

什么是NAPI的生命周期 我们都知道&#xff0c;程序的生命周期是指程序从启动&#xff0c;运行到最后的结束的整个过程。生命周期的管理自然是指控制程序的启动&#xff0c;调用以及结束的方法。 而NAPI中的生命周期又是怎样的呢&#xff1f;如下图所示&#xff1a; 从图上我们…

16、普通数组-除自身以外的数组乘积

思路 通过辅助数组的方式 第一个从左向右的辅助数组乘积第二次从右向左的辅助数组乘积对于0<i<N-1 他的数组乘积就是左边的数组乘积*右边数组乘积然后再分类讨论i0 就是右边1-N-1的数组乘积iN-1就是左边从N-2到0的数组乘积 代码如下&#xff1a; class Solution {pub…

开发日志2024-04-12

开发日志2024/04/12 1、分店月业绩和年业绩都需要添加为真实数据 **开发思路&#xff1a;**分店下所属的技师的业绩总和 代码实现&#xff1a; 前端 无 后端 //TODO 将技师多对应的积分累加到他所属的分店的月/年累计业绩销量中//TODO 查询技师所对应的分店地址String f…

【深度学习】图像超分辨

案例 7&#xff1a;图像超分辨 相关知识点&#xff1a;生成对抗网络、图像处理&#xff08;PIL&#xff09;和可视化&#xff08;matplotlib&#xff09; 1 任务目标 1.1 任务和数据简介 ​ 本次案例将使用生成对抗网络来实现 4 倍图像超分辨任务&#xff0c;输入一张低分辨…

中级物流师、高级物流师资格认证考试大纲《物流管理实务》

物流管理实务 第一章 物流市场调查 一、市场调查基本知识 二、物流市场调研 三、物流市场预测 四、物流市场调研报告 第二章 仓库规划与设计 一、仓储规划概述 二、仓库规模和数量规划 三、仓库选址规划 四、仓库的结构与布局 五、自动化立体仓库的规划与设计 第…

微信小程序报错——“errno“: 600001, “errMsg“: “request:fail -2:net::ERR_FAILED“

bug现象 微信小程序体验版和真机调试 进入小程序的时候接口就出现了这个报错 "errno": 600001, "errMsg": "request:fail -2:net::ERR_FAILED" 排查 检查是证书过期还是证书链不完整 证书的信任链完整问题&#xff0c;可以在 亚数信息-SSL/TLS安…

安装ODBC方法

1、运行 搜索 ODBC数据源管理程序 32位或者 64位 2、在用户DSN或者系统DSN选择添加&#xff08;建议前者&#xff09;&#xff0c;此处以添加access数据库的odbc驱动为例 3、安装成功

Unity让地图素材遮挡人物

点击编辑/项目设置/图形&#xff0c;透明度排序模式设置自定义轴&#xff0c;透明度排序轴Y设置为1其他为0。 此时人物和地图素材的图层排序相等&#xff0c;当人物的高度大于地图素材时&#xff0c;人物则被遮挡。

锚框(anchor box)

目标检测算法通常会在输入图像中抽样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界&#xff0c;从而更准确地预测目标的真实边界框&#xff08;ground-truth bounding box)。不同的模型所使用的区域抽样方法可能不同。这里我们…

三小时零基础入门微信扫码点餐小程序 手把手带你开发一款云开发版点餐软件,店铺地图导航,外卖小程序,用户端和后厨端都有

从今天开始带领大家实现一款云开发版的点餐小程序 视频讲解&#xff1a;《云开发后台微信扫码点餐小程序cms网页管理后台》 技术选型 1&#xff0c;前端 微信小程序原生框架cssJavaScript 2&#xff0c;管理后台 云开发Cms内容管理系统web网页 3&#xff0c;数据后台 小…

【STL】list

目录 1. list的使用 1.1 list的构造 1.2 list iterator的使用 1.3 list capacity 1.4 list element access 1.5 list modifiers 1.6 list的迭代器失效 2. list的模拟实现 3. list与vector的对比 1. list的使用 1.1 list的构造 1.2 list iterator的使用 1. begin与end为…

MySQL前缀索引(3/16)

前缀索引 前缀索引&#xff1a;MySQL支持前缀索引&#xff0c;允许定义字符串的一部分作为索引。如果不指定前缀长度&#xff0c;索引将包含整个字符串。前缀索引可以节省空间&#xff0c;但可能会增加查询时的记录扫描次数&#xff08;因为会查询到多个前缀相同的数据&#x…

4.9QT

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&#xf…

Redis数据持久化 AOF RDB

Redis数据持久化 AOF RDB 1、单点 redis 的问题2、主从复制2.1 命令传播 3、Redis的持久化3.1 AOF写回策略重写机制后台重写 3.2 RDB&#xff08;默认方式&#xff09;RDB 方式&#xff1a;执行快照时&#xff0c;数据能被修改吗&#xff1f;RDB 方式总结 3.3 RDB 和 AOF 组合&…

【springboot开发】MVC和SSM

前言&#xff1a;关于MVC和SSM基本内容的梳理&#xff0c;以及两者之间的关系。 文章目录 1. 三层架构2. MVC3. SSM 1. 三层架构 三层架构是指&#xff1a; 视图层view&#xff08;表现层&#xff09;: 用于显示数据和接收用户输入的数据&#xff0c;为用户提供一种交互式操作…

684. 冗余连接

684. 冗余连接 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;错误经验吸取 原题链接&#xff1a; 684. 冗余连接 https://leetcode.cn/problems/redundant-connection/description/ 完成情况&#xff1a; 解题思路&#xff1a; 这段…

[react优化] 避免组件或数据多次渲染/计算

代码如下 点击视图x➕1,导致视图更新, 视图更细导致a也重新大量计算!!这很浪费时间 function App() {const [x, setX] useState(3)const y x 2console.log(重新渲染, x, y);console.time(timer)let a 0for (let index 0; index < 1000000000; index) {a}console.timeE…

论文阅读AI工具链

文献检索 可以利用智谱清言来生成合适的文献检索式&#xff0c;并根据需要不断调整。 谷歌学术 在Google Scholar中进行检索时&#xff0c;您可以使用类似的逻辑来构建您的搜索式&#xff0c;但是语法会有所不同。Google Scholar的搜索框接受普通的文本搜索&#xff0c;但是…

面试-数据库基础以及MySql、ClickHost、Redis简介

面试-数据库基础以及MySql、ClickHost、Redis简介 0.数据完整性1.数据库并发控制1.1事物1.2 并发读写错误1.3 锁1.3.1 乐观锁与悲观锁1.3.2 共享锁和排他锁1.3.3 行锁与表锁1.3.4 意向锁 1.4 封锁协议与隔离级别1.5 MVCC1.5.1 概念1.5.2 当前读与快照读1.5.3 MVCC in InnoDB 2.…

基于 RisingWave 和 ScyllaDB 构建事件驱动应用

概览 在构建事件驱动应用时&#xff0c;人们面临着两大挑战&#xff1a;1&#xff09;低延迟处理大量数据&#xff1b;2&#xff09;实现流数据的实时摄取和转换。 结合 RisingWave 的流处理功能和 ScyllaDB 的高性能 NoSQL 数据库&#xff0c;可为构建事件驱动应用和数据管道…