《C++ STL:vector类(上)》:详解基础使用核心接口及经典算法题 - 实践

news/2025/10/4 21:00:32/文章来源:https://www.cnblogs.com/yxysuanfa/p/19125926

个人主页:Cx330

❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》《优选算法指南-必刷经典100题》

心向往之行必能至


博主简介:

前言:

在vector类学习之前,大家可以回顾下string类的实现,可以发现我们string类的接口有很多,而vector类的接口比string少了很多,string类比STL诞生要早几年,STL很多容器和string都具有相似性,但是string的很多接口非常鸡肋


目录

前言:

一、vector容器

1.1vector的介绍

1.2对vector的理解

1.3vector的定义

二、vector的使用(结合文档)

2.1无输入输出流——自己实现Print

2.2  迭代器:vector iterator 的使用

2.2.1  概念理解

2.2.2  实践

2.3  vector的空间增长问题

2.3.1  文档接口理解

2.3.2  不同环境下capacity增长倍数问题

2.3.3  reserve:提前将空间设置足够,提高效率

2.3.4  实践

2.4  vector的增删查改

2.4.1  vector也只有尾插和尾删

2.4.2  insert && erase实践

2.5  如果你觉得库里面的不好用可以用自己定义的模版

2.6  简单了解一下emplace

2.6.1  简单了解

2.6.2  对比

2.6.3  实践

三、vector实践:两道算法题

3.1  只出现一次的数字

代码实现

3.2  杨辉三角

C版本:

 C++版本的vector——轻松搞定

算法代码实现

本文代码完整展示

Test.c:

结尾


一、vector容器

1.1vector的介绍

cplusplus中vector类介绍

1.2对vector的理解

string是字符串,vector则是一个改变数据的顺序容器,其实对应的就是博主之前在用C语言实现初阶的数据结构里面实现过的顺序表。可以理解为C++版本的顺序表

1.3vector的定义

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

二、vector的使用(结合文档)

2.1无输入输出流——自己实现Print

vector没法cin、cout,我们要想输出结果,就得自己封装一个Print函数——

void Print(const vector& v)
{for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;
}

也可以范围for来实现

	//范围forfor (auto e : v){cout << e << " ";}cout << endl;

2.2  迭代器:vector iterator 的使用

2.2.1  概念理解
iterator的使用接口说明
(重点)begin+end获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator
rbegin+rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator
2.2.2  实践
	vector::const_iterator it = v.begin();while (it != v.end()){cout << "it" << " ";++it;}cout << endl;

这个可以封装到Print函数里面

void Print(const vector& v)
{//for (size_t i = 0; i < v.size(); i++)//{//	cout << v[i] << ' ';//}//cout << endl;//for (auto e : v)//{//	cout << e << ' ';//}//cout << endl;vector::const_iterator it = v.begin();while (it != v.end()){cout << *it << ' ';++it;}cout << endl;
}

调用前面已经封装好的Print函数,构造、输出

void test_vector1()
{vector v1;vector v2(10, 1);vector v3(v2);vector v4(v3.begin(), v3.end());string s1("xxxxxxxx");vector v5(s1.begin(), s1.end());vector v6 = { 1,2,3,4,5 };Print(v2);Print(v5);Print(v6);auto il = { 1,2,3,4 };for (auto e : il){cout << e << " ";}cout << endl;
}

2.3  vector的空间增长问题

2.3.1  文档接口理解
容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector的capacity

(1)capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。VS是PJ版本STL,g++是SGI版本STL。

(2)reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。

(3)resize在开空间的同时还会进行初始化,影响size

2.3.2  不同环境下capacity增长倍数问题

我们来测试一下vector的默认扩容机制

// 测试vector的默认扩容机制
void TestVectorExpand()
{size_t sz;vector v;sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}

vs环境下的运行结果:vs下使用的STL基本是按照1.5倍方式扩容

making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 3
capacity changed: 4
capacity changed: 6
capacity changed: 9
capacity changed: 13
capacity changed: 19
capacity changed: 28
capacity changed: 42
capacity changed: 63
capacity changed: 94
capacity changed: 141

VS是按第一次2倍、后面1.5倍进行扩容的

g++是按2倍进行扩容的

2.3.3  reserve:提前将空间设置足够,提高效率

如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够,这样就可以避免边插入边扩容导致效率低下的问题了——主要是避免一边插入一边扩容

// 如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够
// 就可以避免边插入边扩容导致效率低下的问题了
void TestVectorExpandOP()
{vector v;size_t sz = v.capacity();v.reserve(100);   // 提前将容量设置好,可以避免一遍插入一遍扩容cout << "making bar grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}
2.3.4  实践
void test_vector2()
{//vector v1;//v1.reserve(100);//size_t old = v1.capacity();//cout << v1.capacity() << endl;//for (size_t i = 0; i < 100; i++)//{//	v1.push_back(i);//	if (old != v1.capacity())//	{//		cout << v1.capacity() << endl;//		old = v1.capacity();//	}//}vector v1;const int n = 100;v1.reserve(n);size_t old = v1.capacity();//cout << v1.capacity() << endl;size_t begin = clock();for (size_t i = 0; i < n; i++){v1.push_back(i);//if (old != v1.capacity())//{//	cout << v1.capacity() << endl;//	old = v1.capacity();//}}size_t end = clock();cout << end - begin << endl;vector v2;v2.resize(100, 1);Print(v2);
}

2.4  vector的增删查改

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

和string一样,vector也只有尾插和尾删,没有头插和头删,因为要挪动数据,效率太低了

我们要头插、或者头删和string一样,直接用insert和erase就行

2.4.2  insert && erase实践
void test_vector3()
{vector v1 = { 1,2,3 };v1.push_back(4);Print(v1);//头插v1.insert(v1.begin(), 0);Print(v1);v1.insert(v1.begin() + 3, 0);Print(v1);//头删v1.erase(v1.begin());Print(v1);v1.erase(v1.begin() + 3);Print(v1);
}

2.5  如果你觉得库里面的不好用可以用自己定义的模版

这个要当心,这个如果不用就注释掉,否则会跟库冲突

2.6  简单了解一下emplace

2.6.1  简单了解

emplace可以简单理解为功能和insert差不多,而emplace_back和push_back功能一样,但前者效果更好,这个emplace我们在C++11会细讲

2.6.2  对比

2.6.3  实践
void test_vector4()
{AA aa1 = { 0,0 };vector v1 = { aa1,{1,1},{2,2},{3,3} };auto it = v1.begin();while (it != v1.end()){cout << it->_a1 << ' ' << it->_a2 << endl;++it;}cout << endl;v1.push_back(aa1);v1.emplace_back(aa1);//差异v1.push_back({ 1, 1 });//既可以传AA对象,又可以传构造AA对象的参数v1.emplace_back(2, 2);//只能传AA对象it = v1.begin();while (it != v1.end()){cout << it->_a1 << ' ' << it->_a2 << endl;++it;}cout << endl;
}


三、vector实践:两道算法题

3.1  只出现一次的数字

力扣链接:136. 只出现一次的数字

题目描述:

题目示例:

代码实现

代码演示如下

class Solution {
public:int singleNumber(vector& nums){int val=0;for(auto e:nums){val^=e;}return val;}
};

时间复杂度:O(n),空间复杂度:O(1)。

3.2  杨辉三角

力扣链接:118. 杨辉三角

题目描述:

题目示例:

C版本:

麻不麻烦?麻烦!我们如果用C语言来实现的话,就要动态开辟二维数组——开辟指针数组,这个指针数组是指向数组的指针,或者这样理解:这个数组里面存放了指向数组的指针

 C++版本的vector——轻松搞定

不用指针,用容器怎么表示二维数组呢?vector<vector<int>>

算法代码实现

代码:

class Solution {
public:vector> generate(int numRows) {vector> vv;//定义行vv.resize(numRows,vector());//定义列for(size_t i = 0;i < numRows;++i){vv[i].resize(i + 1,1);//1}for(size_t i = 2;i < vv.size();++i)//第0、1行的都不需要处理,1{for(size_t j = 1;j < vv[i].size() - 1;++j){vv[i][j] = vv[i-1][j] + vv[i-1][j-1];}}return vv;}
};

时间复杂度:O(n),空间复杂度:O(1)。

本文代码完整展示

Test.c:

#include
#include
using namespace std;
void Print(const vector& v)
{//for (size_t i = 0; i < v.size(); i++)//{//	cout << v[i] << ' ';//}//cout << endl;//for (auto e : v)//{//	cout << e << ' ';//}//cout << endl;vector::const_iterator it = v.begin();while (it != v.end()){cout << *it << ' ';++it;}cout << endl;
}
void test_vector1()
{vector v1;vector v2(10, 1);vector v3(v2);vector v4(v3.begin(), v3.end());string s1("xxxxxxxx");vector v5(s1.begin(), s1.end());vector v6 = { 1,2,3,4,5 };Print(v2);Print(v5);Print(v6);auto il = { 1,2,3,4 };for (auto e : il){cout << e << " ";}cout << endl;
}
void test_vector2()
{//vector v1;//v1.reserve(100);//size_t old = v1.capacity();//cout << v1.capacity() << endl;//for (size_t i = 0; i < 100; i++)//{//	v1.push_back(i);//	if (old != v1.capacity())//	{//		cout << v1.capacity() << endl;//		old = v1.capacity();//	}//}vector v1;const int n = 100;v1.reserve(n);size_t old = v1.capacity();//cout << v1.capacity() << endl;size_t begin = clock();for (size_t i = 0; i < n; i++){v1.push_back(i);//if (old != v1.capacity())//{//	cout << v1.capacity() << endl;//	old = v1.capacity();//}}size_t end = clock();cout << end - begin << endl;vector v2;v2.resize(100, 1);Print(v2);
}
void test_vector3()
{vector v1 = { 1,2,3 };v1.push_back(4);Print(v1);//头插v1.insert(v1.begin(), 0);Print(v1);v1.insert(v1.begin() + 3, 0);Print(v1);//头删v1.erase(v1.begin());Print(v1);v1.erase(v1.begin() + 3);Print(v1);
}
struct AA {int _a1 = 1;int _a2 = 1;AA(int a1 = 1, int a2 = 1):_a1(a1), _a2(a2){}
};
void test_vector4()
{AA aa1 = { 0,0 };vector v1 = { aa1,{1,1},{2,2},{3,3} };auto it = v1.begin();while (it != v1.end()){cout << it->_a1 << ' ' << it->_a2 << endl;++it;}cout << endl;v1.push_back(aa1);v1.emplace_back(aa1);//差异v1.push_back({ 1, 1 });//既可以传AA对象,又可以传构造AA对象的参数v1.emplace_back(2, 2);//只能传AA对象it = v1.begin();while (it != v1.end()){cout << it->_a1 << ' ' << it->_a2 << endl;++it;}cout << endl;
}
//template
//class vector {
//paivate:
//	T* _str;
//	size_t size;
//	size_t capacity;
//};
int main()
{test_vector4();return 0;
}

结尾

往期回顾:

《一篇拿下C++:string类(详解版)》:教你如何从入门到避坑再到玩转字符串问题

总结:这篇博客到此为止,给大家分享了vector类的接口使用,那么下篇博客我将给大家分享vector的底层,如果这篇文章对你有帮助的话,可以给博主一键四连哦

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

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

相关文章

伪静态网站入侵浙江江能建设有限公司网站

Azure DevOps Server (原名TFS)是微软公司的软件开发管理平台&#xff0c;也是著名的软件开发过程管理工具&#xff1b;系统中记录了软件开发过程中的需求、问题、缺陷和迭代计划等各种软件开发工作项数据。 对于工作项数据的批量操作(例如新增和编辑)&#xff0c;Excel是一个非…

数据结构 - 跳表 Skip List

跳表(Skip List)是一种用于查找的类似于链表的数据结构,是对有序链表的改进,能够在 \(O(\log{n})\) 时间内完成增加、删除、查找操作。跳表相比于树堆与红黑树,其功能与性能相当,并且跳表的代码长度相较下更短。…

06. 定时器

一、定时器QML 有一个 Timer元素,它允许你在 QML 中设置定时器。这个元素是 Qt Quick 模块的一部分。我们可以通过定时器的 interval 属性设置 定时间隔,通过 running 属性设置 定时器默认是否运行,通过 repeat 属性…

高端集团网站建设公司铭万做的网站怎么样

11.盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明&#xff1a;你不能倾…

怎么自己建立网站站长之家seo

前言 Gitee 是一个中国的开源代码托管平台&#xff0c;类似于 GitHub&#xff0c;旨在为开发者提供一个高效、稳定、安全的代码管理和协作开发环境。Gitee 支持 Git 协议&#xff0c;可以托管 Git 仓库&#xff0c;进行版本控制、代码协作、项目管理等操作。 1. Gitee 的主要…

职业学院网站建设网站建设需要哪些资质

这是渲染的数据 这是生成的pdf文件&#xff0c;直接可以打印 需要安装和npm依赖和引入封装的pdf.js文件 npm install --save html2canvas // 页面转图片 npm install jspdf --save // 图片转pdfpdf.js文件 import html2canvas from "html2canvas"; import jsPDF …

没人做网站了吗重庆建设网站哪家专业

ArcGIS软件可以很方便的直接实现度分秒转度、度转度分秒(度分秒→度、度→度分秒)。 文章目录 一、转换预览二、工具介绍三、案例解析一、转换预览 借助ArcGIS快速实现度分秒与度及其他格式的坐标转换,例如:度分秒→度、度→度分秒。 1. 度→度分秒 2. 度分秒→度 转换后…

硬件-电容学习DAY23——电容设计实战指南:从选型到高频应用 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

NOIP之前的复健记录

写一些做题记录,题解和随机话。 这回真是高一零基础学OI/文化课了。CF547B考虑每一个数对答案的贡献。 自然是当这个数 \(a_i\)是所选的区间最小值时对答案有贡献,所以我们找到左边第一个比 \(a_i\) 大的数 \(a_l\) …

支付网站开发建设费用怎么入账网站建设设计服务公司

了解细胞对基因扰动的反应是许多生物医学应用的核心&#xff0c;从识别癌症中涉及的基因相互作用到开发再生医学方法。然而&#xff0c;可能的多基因扰动数量的组合爆炸严重限制了实验验证。在这里&#xff0c;作者提出了图增强的基因激活和抑制模拟器&#xff08;GEARS&#x…

Linux 命令行安装达梦数据库

达梦官方不提供 docker 镜像了,由于要开发国产化项目,因此只能暂时在 Linux 服务器上直接安装。如果 Linux 操作系统带有图形化界面的话,安装起来很简单,参考官网即可,这里不再赘述。有的客户现场提供的 Linux 服…

Google开源Tunix:JAX生态的LLM微调方案来了

AX生态这两年在LLM训练这块追赶得挺快。PyTorch虽然还是主流但JAX在并行计算、TPU加速和API组合性上确实有些独特的优势。Google今天放出了Tunix这个库,专门做LLM的后训练——微调、强化学习、知识蒸馏这些都能搞。 T…

域名和空间都有了怎么做网站三门峡网站制作

原标题&#xff1a;鸿蒙OS 2.0系统正式发布&#xff01;余承东&#xff1a;明年华为系手机将会搭载由于众所周知的原因&#xff0c;华为手机这两年过的很艰难&#xff0c;尤其是今年力度大了后&#xff0c;华为手机接下来可能面临无芯片可用的严重情况。而除了一些硬件外&#…

看上去高端的网站兰州建设局网站

全文共2485字&#xff0c;预计学习时长12分钟图源&#xff1a;unsplash数据科学的生命周期主要包括数据收集、数据清理、探索性数据分析、模型构建和模型部署。作为数据科学家或机器学习工程师&#xff0c;能够部署数据科学项目非常重要&#xff0c;这有助于完成数据科学生命周…

网站服务方案2022昆明今天刚刚发生的新闻

常用类 目录 1. QString 字符串类&#xff08;掌握&#xff09; 2. 容器类&#xff08;掌握&#xff09; 2.1 顺序容器QList 2.2 关联容器QMap 3. 几种Qt数据类型&#xff08;熟悉&#xff09; 3.1 跨平台数据类型 3.2 QVariant 统一数据类型 3.3 QStringList 字符串列表 4. QD…

实用指南:如何优化 C# MVC 应用程序的性能

实用指南:如何优化 C# MVC 应用程序的性能2025-10-04 20:30 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: blo…

软件工程的第一次作业

软件工程的第一次作业这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/202501SoftwareEngineering这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/202501SoftwareEngineering/homework/13546这个作…

实用指南:Matlab通过GUI实现点云的快速全局配准(FGR)

实用指南:Matlab通过GUI实现点云的快速全局配准(FGR)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&qu…

Eclipse 中文语言包安装教程:一键将界面切换为中文 - 教程

Eclipse 中文语言包安装教程:一键将界面切换为中文 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consol…

『OI 回忆录』停课有感

原来已经快 2 年了吗。怀恋啊。时值 11.17 晚 20:11。 停课结束了。写一篇文章。\(\text{Schedule}\)开心是一天,不开心也是一天。11.11 第一次和高中联考,获得了 125 pts 的好成绩。11.11 并且得知自己去不了 NOIP,…