C++STL 6大组件—你必知必会的编程利器


课程总目录


文章目录

  • 一、vector容器
  • 二、deque和list容器
  • 三、vector、deque、list横向对比
  • 四、详解容器是配置stack、queue、priority_queue
  • 五、无序关联容器
  • 六、有序关联容器
  • 七、迭代器
  • 八、函数对象
  • 九、泛型算法和绑定器


一、vector容器

底层数据结构是动态开辟的数组,每次以原来空间大小的2倍进行扩容

使用前需要包含头文件:#include <vector>

容器中对象的构造析构,内存的开辟释放,是通过空间配置器allocator实现:allocate(内存开辟)、deallocate(内存释放)、construct(对象构造)、destroy(对象析构)

使用方法:

vector<int> vec;

增加:

  • vec.push_back(20);,在容器末尾增加一个元素,时间复杂度O(1),有可能会导致容器扩容
  • vec.insert(it, 20);,在迭代器it指向的位置增加一个元素,时间复杂度O(n),有可能会导致容器扩容

删除:

  • vec.pop_back();,在容器末尾删除一个元素,时间复杂度O(1)
  • vec.erase(it);,删除迭代器it指向的元素,时间复杂度O(n)

查询:

  • 提供了operator[]重载函数,数组下标的随机访问,例如vec[5],时间复杂度O(1)
  • iterator,迭代器进行遍历,一定要考虑迭代器失效问题
  • findfor_each等泛型算法
  • C++11提供的语法糖foreach,其实就是通过迭代器来实现的

注意:对容器进行连续插入或者删除操作(insert/erase),一定要更新迭代器,否则第一次insert或者erase之后,迭代器就失效了,失效问题详见这里

常用方法:

  • size();,返回容器底层有效元素的个数
  • empty();,判断容器是否为空
  • reserve();,为vector预留空间,只给容器底层开辟指定大小空间并不添加新的元素
  • resize();,扩容,不仅给容器底层开辟指定大小空间,还会添加新的元素
  • swap();,两个容器进行元素交换

代码示例:元素遍历

vector<int> vec;
for (int i = 0; i < 20; ++i)vec.push_back(i);int size = vec.size();
for (int i = 0; i < size; ++i)cout << vec[i] << " ";
cout << endl;auto it1 = vec.begin();
for (; it1 != vec.end(); ++it1)cout << *it1 << " ";
cout << endl;

运行结果:

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

代码示例:删除所有偶数

vector<int> vec;
for (int i = 0; i < 20; ++i)vec.push_back(i);auto it = vec.begin();
while (it != vec.end())
{if (*it % 2 == 0)it = vec.erase(it);else++it;
}int size = vec.size();
for (int i = 0; i < size; ++i)cout << vec[i] << " ";
cout << endl;

运行结果:

1 3 5 7 9 11 13 15 17 19

代码示例:所有奇数前面加一个比其小1的数

vector<int> vec;
for (int i = 0; i < 20; ++i)vec.push_back(i);for (auto it = vec.begin(); it != vec.end(); ++it)
{if (*it % 2 == 1){it = vec.insert(it, *it - 1);++it;}
}int size = vec.size();
for (int i = 0; i < size; ++i)cout << vec[i] << " ";
cout << endl;

运行结果:

0 0 1 2 2 3 4 4 5 6 6 7 8 8 9 10 10 11 12 12 13 14 14 15 16 16 17 18 18 19

代码示例:reserve预留空间

reserve只是预留空间,只给容器底层开辟指定大小空间并不添加新的元素

默认定义的vector底层开辟空间为0,第一次push_back插入从0变更为1,再变为2,4,8,16,32…,一直进行二倍扩容,扩容频繁,效率太低,假如开始知道问题的数据量大小,即可使用reserve预留空间

vector<int> vec;
vec.reserve(20);cout << vec.empty() << endl;
cout << vec.size() << endl;for (int i = 0; i < 20; ++i)vec.push_back(i);cout << vec.empty() << endl;
cout << vec.size() << endl;

运行结果:

1
0
0
20

代码示例:resize扩容

resize扩容,不仅给容器底层开辟指定大小空间,还会添加新的元素,没有指定添加的元素值则为0

vector<int> vec;
vec.resize(10);cout << vec.empty() << endl;
cout << vec.size() << endl;for (int i = 0; i < 20; ++i)vec.push_back(i);cout << vec.empty() << endl;
cout << vec.size() << endl;int size = vec.size();
for (int i = 0; i < size; ++i)cout << vec[i] << " ";
cout << endl;

运行结果:

0
10
0
30
0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

若改为vec.resize(10,3);,则运行结果为:

0
10
0
30
3 3 3 3 3 3 3 3 3 3 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

二、deque和list容器

deque:使用前需要包含头文件:#include <deque>

双端队列容器,底层数据结构为动态开辟的二维数组。 一维数组从2开始,以2倍的方式进行扩容,每次扩容后,原来第二维的数组,从新的第一维数组的下标oldsize/2开始存放(也就是扩容之后的中间),前后都预留相同的空行,方便支持双端的元素添加

在这里插入图片描述
随着元素增加:
在这里插入图片描述
如果继续增加呢?会对第一维扩容
在这里插入图片描述
使用方法:

deque<int> deq;

增加:

  • deq.push_back(20);,从末尾添加元素,时间复杂度O(1),可能引起扩容
  • deq.push_front(20);,从首部添加元素,时间复杂度O(1),可能引起扩容。vector中没有该方法,需要使用vec.insert(vec.begin(), 20),O(n)
  • deq.insert(it, 20);,迭代器it指向的位置添加元素,时间复杂度O(n)

删除:

  • deq.pop_back();,从末尾删除元素,时间复杂度O(1)
  • deq.pop_front();,从首部删除,时间复杂度O(1)
  • deq.erase(it);,迭代器it指向的位置进行元素删除,时间复杂度O(n)

查询:

  • iterator,迭代器进行遍历,一定要考虑迭代器失效问题(连续的inserterase

常用方法:

  • size();,返回容器底层有效元素的个数
  • empty();,判断容器是否为空
  • resize();,扩容,不仅给容器底层开辟指定大小空间,还会添加新的元素
  • swap();,两个容器进行元素交换

list:使用前需要包含头文件:#include <list>

底层数据结构为双向循环链表,结点中包括data、pre、next

vectordeque不同,list允许高效地在任何位置插入和删除元素,但不支持随机访问

使用方法:

list<int> MyList;

增加:

  • MyList.push_back(20);,从末尾添加元素,时间复杂度O(1),可能引起扩容
  • MyList.push_front(20);,从首部添加元素,时间复杂度O(1),可能引起扩容
  • MyList.insert(it, 20);,迭代器it指向的位置添加元素,时间复杂度O(1),但是往往要考虑搜索到指定位置的时间

删除:

  • MyList.pop_back();,从末尾删除元素,时间复杂度O(1)
  • MyList.pop_front();,从首部删除,时间复杂度O(1)
  • MyList.erase(it);,迭代器it指向的位置进行元素删除,时间复杂度O(1),但是往往要考虑搜索到指定位置的时间

查询:

  • iterator,迭代器进行遍历,一定要考虑迭代器失效问题(连续的inserterase

常用方法:

  • size();,返回容器底层有效元素的个数
  • empty();,判断容器是否为空
  • resize();,扩容,不仅给容器底层开辟指定大小空间,还会添加新的元素
  • swap();,两个容器进行元素交换

dequelist的使用实例与vector类似,这里就不再写了

三、vector、deque、list横向对比

vector特点:底层是动态开辟的数组,内存是连续的,以2倍的方式进行扩容。当我们默认定义一个vector时候vector<int> vec;,容器底层没有开辟空间,当添加元素时候才开始以0 -> 1 -> 2 -> 4 -> 8...这种方式进行扩容,用原来老内存上的对象在新内存的空间上进行拷贝构造,再析构老内存上的对象并释放老内存,扩容效率低下。我们可以用reserve函数预留空间,但注意reserve并未添加元素

deque特点:底层是动态开辟的二维数组空间,第二维是固定长度的数组空间,扩容时候(第一维的数组进行2倍扩容,原来的第二维的数组放入新扩容的数组中间,即oldsize/2的位置),前后插入删除操作的时间复杂度都是O(1)
那么,deque底层的内存是否是连续的呢?
并不是!deque的第二维都是独立new出来的,也就是说,每一个第二维是连续的,并不是所有的第二维连续,可以说是分段连续

vector与deque之间的区别:

  1. 底层数据结构:看上面两者的特点
  2. 前后删除元素的时间复杂度:末尾插入删除都为O(1),但在最前面进行元素添加删除时候dequeO(1)vectorO(n)。那么,如果现在需求是前后都能插入删除,就选择deque而不选择vector
  3. 内存使用效率vector低,因为vector需要的内存空间必须是连续的;deque第二维内存空间分段连续就行,不用整片连续,可以分块进行数据存储,对内存使用效率更高
  4. 在中间进行insert或者erasevectordeque的效率:它们时间复杂度都为O(n),但vector内存完全连续,在中间进行插入删除元素的时候容易移动;但deque的第二维内存不完全连续,例如在删除一个元素之后,其他元素会一个一个往前挪动,会进行不同内存片段之间的挪动,元素移动更加麻烦一些,效率不如vector
    在这里插入图片描述

vector与list之间的区别:

  1. 底层数据结构:动态开辟的数组 vs 双向循环链表。那也就是在问数组和链表之间的区别
  2. 数组增加删除O(n),查找O(n),随机访问为O(1)
  3. 链表增加删除一个结点本身为O(1),但查找某元素的时间为O(n)
  4. 那么,如果增加删除使用多,优先使用list;如果随机访问使用多,优先使用vector

四、详解容器是配置stack、queue、priority_queue

五、无序关联容器

六、有序关联容器

七、迭代器

八、函数对象

九、泛型算法和绑定器

还有一些STL方面的总结,可以看看这篇文章:C++STL容器内容总结

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

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

相关文章

Ai指令优化文章成爆款实战记录6.26

大家好&#xff0c;我是网创有方的站长&#xff0c;继上篇文章出来之后&#xff0c;立马测试了一翻&#xff0c;没想到第一篇就出来了小爆款。展现量当天3万多&#xff0c;阅读量也有7000多的一个数据。虽说不是很高&#xff0c;相比平常几十的阅读量来说&#xff0c;进步还是非…

process.cwd()与__dirname的区别

process.cwd() 是当前执行node命令时候的文件夹地址 ——工作目录&#xff0c;保证了文件在不同的目录下执行时&#xff0c;路径始终不变__dirname 是被执行的js 文件的地址 ——文件所在目录 在electron进程中使用 如果使用__dirname则会读取到当前运行目录(dist_electron)下…

【大模型】大模型微调方法总结(二)

1.Adapter Tuning 1.背景 2019年谷歌的研究人员首次在论文《Parameter-Efficient Transfer Learning for NLP》提出针对 BERT 的 PEFT微调方式&#xff0c;拉开了 PEFT 研究的序幕。他们指出&#xff0c;在面对特定的下游任务时&#xff0c;如果进行 Full-Fintuning&#xff0…

【yolov8:metrics = model.val()报错TypeError: int() 】

今天在运行yolov8的val模型测验时报错&#xff1a; TypeError: int() argument must be a string, a bytes-like object or a number, not ‘KeyboardModifier’ 看了很多博主和文章&#xff0c;最后找到了解决方法&#xff1a; 在代码头部使用以下代码&#xff0c;重新运行…

python turtle 004Hello Kity

代码&#xff1a;pythonturtle004HelloKity资源-CSDN文库 # 作者V w1933423 import math import turtle as t# 设置画笔速度 t.speed(0)# 定义函数画弧 def myarc(t1, r, angle):arc_length 2 * math.pi * r * angle / 360 # 弧长n int(arc_length / 3) 1 # 分割段数step…

【大模型】大模型微调方法总结(三)

1. Prefix-tuning 1.背景 2021年论文《Prefix-Tuning: Optimizing Continuous Prompts for Generation》中提出了 Prefix Tuning 方法。与Full-finetuning 更新所有参数的方式不同&#xff0c;该方法是在输入 token 之前构造一段任务相关的 virtual tokens 作为 Prefix&#x…

二叉树——对称二叉树

目录 1&#xff1a;题目分析及思路 2&#xff1a;代码实现和分析 1&#xff1a;代码 2&#xff1a;分析 1&#xff1a;题目分析及思路 这里我们有一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 思路&#xff1a; 如上图&#xff0c;示例1是一颗对称的二叉树&a…

基于JSP的列车票务信息管理系统

开头语&#xff1a; 你好&#xff0c;我是专注于计算机科学与技术研究的学长。如果你对列车票务信息管理系统感兴趣或有相关需求&#xff0c;欢迎联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDE、数据库管理工具…

反射及动态代理

反射 定义&#xff1a; 反射允许对封装类的字段&#xff0c;方法和构造 函数的信息进行编程访问 图来自黑马程序员 获取class对象的三种方式&#xff1a; 1&#xff09;Class.forName("全类名") 2&#xff09;类名.class 3) 对象.getClass() 图来自黑马程序员 pac…

pytest-yaml-sanmu(五):跳过执行和预期失败

除了手动注册标记之外&#xff0c;pytest 还内置了一些标记可直接使用&#xff0c;每种内置标记都会用例带来不同的特殊效果&#xff0c;本文先介绍 3 种。 1. skip skip 标记通常用于忽略暂时无法执行&#xff0c;或不需要执行的用例。 pytest 在执行用例时&#xff0c;如果…

LATR 算法解读

文章目录 1. 论文2. 环境安装3. 代码解读3. 1 初始化 lane query3.1.1 SparseInsDecoder3.1.2 loss 计算3.1.3 初始化instance query3.2 ref points 的生成3.3 lane query 和feats进行attention3.3.1 self attn3.3.1 cross attn4. 参考1. 论文 2. 环境安装 146 [2024-06-20 10…

收款机TTS语音芯片新方案:WT3000T8,双语合成流畅,字库解码多样!

发布时间&#xff1a;2024-06-26 09:20 浏览次数&#xff1a;88次 一&#xff1a;方案背景概述 随着科技的飞速发展&#xff0c;人工智能和语音识别技术在各个领域都得到了广泛应用。其中&#xff0c;文本转语音&#xff08;TTS&#xff09;技术以其独特的优势&#xff0c;在收…

基于springboot+vue的梦幻玩具乐园的设计与实现(在线购物平台)

需要源码和论文的小伙伴可以私信博主&#xff08;有偿&#xff09; ​​​​​课题目的与意义 随着互联网的不断普及与在线销售平台的迅猛发展&#xff0c;在线购物日益受到广大消费者的青睐与追捧。通过构建基于Spring BootVue的在线玩具商城&#xff0c;可以为玩具制造商、…

如何快速交付网络基础设施运维管理软件项目?

​ 基于nVisual网络基础设施数字孪生管理工具 开发项目需求 项目交付成本节省50%、进度提高100% ​ &#xff1e;&#xff1e;&#xff1e;nVisual主要功能&#xff1c;&#xff1c;&#xff1c; 01 场 景 ★ 支持层次化的场景结构 ★ 支持多种空间场景 ​ 02 规 划 ★ 丰…

基于Pytorch框架的深度学习ConvNext神经网络宠物猫识别分类系统源码

第一步&#xff1a;准备数据 12种宠物猫类数据&#xff1a;self.class_indict ["阿比西尼猫", "豹猫", "伯曼猫", "孟买猫", "英国短毛猫", "埃及猫", "缅因猫", "波斯猫", "布偶猫&q…

Go语言之函数和方法

个人网站&#xff1a; http://hardyfish.top/ 免费书籍分享&#xff1a; 资料链接&#xff1a;https://url81.ctfile.com/d/57345181-61545511-81795b?p3899 访问密码&#xff1a;3899 免费专栏分享&#xff1a; 资料链接&#xff1a;https://url81.ctfile.com/d/57345181-6…

学习TS看这一篇就够了!

目录 TS的优点和缺点基础类型数字类型布尔类型字符串类型void 类型null 类型和 undefined 类型bigint类型Symbol类型 其他类型数组元组枚举Enum对象和函数any void never unknown 的区别是什么泛型 Generic交叉类型联合类型 特殊符号 ? ?. ?? ! _修饰符 TS的优点和缺点 优…

如何集成CppCheck到visual studio中

1.CPPCheck安装 在Cppcheck官方网站下载最新版本1.70&#xff0c;官网链接&#xff1a;http://cppcheck.sourceforge.net/ 安装Cppcheck 2.集成步骤 打开VS&#xff0c;菜单栏工具->外部工具->添加&#xff0c;按照下图设置&#xff0c;记得勾选“使用输出窗口” 2.…

word2016中新建页面显示出来的页面没有页眉页脚,只显示正文部分。解决办法

问题描述&#xff1a;word2016中新建页面显示出来的页面没有页眉页脚&#xff0c;只显示正文部分。设置了页边距也不管用。 如图1 图1 解决&#xff1a; 点击“视图”——“多页”——“单页”&#xff0c;即可。如图2操作 图2 结果展示&#xff1a;如图3 图3

AI 大模型之美 | 更新完结

AI 大模型&#xff1a;技术的壮丽与美感 在当今的人工智能领域&#xff0c;大模型如同一座座巨大的桥梁&#xff0c;将计算机科学、语言学、认知科学等多个领域连接在一起。它们不仅仅是技术的象征&#xff0c;更是人类智慧与创新的结晶。本文将探讨AI大模型的壮丽与美感&…