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.mfbz.cn/a/745901.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python在Excel中设置数字格式和获取应用数字格式后的值

目录 安装Python Excel库 Python在Excel中设置数字格式 Python获取Excel中应用数字格式的单元格的显示值 总结 Excel 数字格式是用于控制单元格中数字显示方式的一组规则或代码。通过设置不同的数字格式&#xff0c;可以定义数字的显示方式&#xff0c;如小数位数、货币符号…

树形结构的勾选、取消勾选、删除、清空已选、回显、禁用

树形结构的勾选、取消勾选、删除、清空已选、回显、禁用 基本页面&#xff1a; 分为上传文件和编辑的页面 代码实现要点&#xff1a; 上传文件页面&#xff1a; 点开选择范围弹窗&#xff0c;三个radio单选框都为可选状态&#xff0c;默认显示的是第一个单选框&#xff08;按…

前端实战:实现块级元素的拖拽与缩放功能

在现代网页开发中&#xff0c;用户交互是一个非常重要的部分。在这篇文章中&#xff0c;我们将详细介绍如何使用原生 JavaScript 实现块级元素的拖拽与缩放功能。具体来说&#xff0c;我们将实现以下功能&#xff1a; 点击并拖动 outer 元素&#xff0c;可以移动整个块。点击并…

GPT-5的即将登场

人工智能领域正经历着一场前所未有的变革&#xff0c;而其中大语言模型的进步尤为瞩目。继GPT-4取得巨大成功后&#xff0c;OpenAI即将推出的GPT-5被寄予厚望。作为新一代大语言模型&#xff0c;GPT-5在各个方面都有望实现显著突破。本文将探讨GPT-5的潜在特性、应用前景以及其…

基于Flask开发的前后端交互项目(可用于期末大作业) MySQL数据库 文件上传 Spider爬虫 Echarts可视化展示 JS动态

项目描述&#xff1a; 开发一个基于Flask框架开发的前后端交互项目&#xff0c;项目内容为 东京奥运会 。对各个需要填写的字段做了数据验证&#xff0c;非法信息会被JS拦截提醒不合法&#xff1b;还对未登录就访问做了拦截&#xff0c;阻止未登录就访问。 前端&#xff1a;HT…

优思学院|精益生产3大特征、5个步骤、8大浪费、10大工具

前言 精益生产作为一种先进的生产管理理念&#xff0c;起源于丰田汽车公司的生产方式&#xff0c;其核心在于消除浪费、优化流程&#xff0c;以最少的投入获取最大的产出。本文将详细解析精益生产的三大特征、五个步骤、八大浪费和十大工具&#xff0c;帮助读者深入理解这一理…

含着“金钥匙”出生,“凤凰”重塑骨科未来!

凤凰&#xff0c;作为中华传统文化中的神鸟&#xff0c;象征着吉祥、和谐与重生。而Phoenix&#xff08;凤凰&#xff09;&#xff0c;这个名字本身就带有传奇色彩。 2024年6月20日-23日&#xff0c;由中国医师协会、中国医师协会骨科医师分会主办&#xff0c;江苏省医师协会骨…

【openmpi】怎样使用openmpi并行运行python脚本?

创作日志&#xff1a; 装过一次openmpi&#xff0c;但是半年之后就忘记怎么用了&#xff0c;所以记录一下 1. 测试openmpi是否安装好 cd /home/xxxx/SnapHiC_Call_Loop/openmpi-4.1.6/examples make mpirun -np 4 hello_c得到如下输出就说明是装好的了 2. 没有导入路径的话导…

智能护栏碰撞监测系统:强化道路安全的智能守卫

智能护栏碰撞监测系统是提升道路安全、加强交通管理智能化的重要技术手段&#xff0c;其为道路安全带来的好处和安装的必要性体现在以下几个方面&#xff1a; 1. 即时事故响应&#xff1a;系统能够实时监测到护栏遭受的碰撞事件&#xff0c;几乎瞬间触发报警机制&#xff0c;将…

服务器如何实现SSH免密码登录?

目录 一、服务器和电脑的区别二、什么是SSH三、什么是免密码登录四、服务器如何实现SSH免密码登录 一、服务器和电脑的区别 服务器和电脑是两种不同类型的计算机系统&#xff0c;它们在设计、功能和用途上存在明显的区别。首先&#xff0c;从硬件配置上看&#xff0c;服务器通…

408计算机网络--物理层

一、物理层概述 物理层是干嘛使得&#xff1f; 物理层解决如何在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。 物理层主要任务是确定与传输媒体接口有关的一些特性。定义标准可以理解为插排上的两孔三孔 机械特性&#xff1a;定义物理连接…

ONLYOFFICE8.1版本桌面编辑器的测评

首先我们先出示一下我们所测评官网的链接&#xff1a; ONLYOFFICE官网链接&#xff1a;ONLYOFFICE - 企业在线办公应用软件 | ONLYOFFICE 我们这款ONLYOFFICE8.1版本有这一下优点 1.解决PDF痛点 ONLYOFFICE在PDF编辑方面支持高亮显示、下划线和删除线、添加批注等功能&#…

vue3集成Echarts,自定义ToolBox时无法监听参数变化

问题描述 在vue中集成echart中自定义ToolBox工具的点击事件&#xff0c;并将里面的typeBar赋给data中的变量&#xff0c;随后用watch监听这个变量的变化&#xff0c;发现监听不到&#xff01;&#xff01;&#xff01;&#xff01; 解决方案&#xff1a;一直以为是watch不能监…

jenkins构建allure报java.io.IOException: Can‘t find allure commandline <null>

jenkins构建allure报错 java.io.IOException: Can’t find allure commandline 配置allure commandline&#xff0c;注意将地址放在bin上一层

链式结构二叉树练习

一.二叉树的前序遍历 想要输出所给值&#xff0c;就要先用数组将数据存储起来&#xff0c;所以这里我们单独创建一个前序遍历函数&#xff0c;将所要数据前序遍历并放入数组&#xff0c;代码如下&#xff1a; void preOrder(struct TreeNode* root, int* a, int* pi)//前序遍历…

鸿蒙开发系统基础能力:【@ohos.pasteboard (剪贴板)】

剪贴板 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import pasteboard from ohos.pasteboard;属性 系统能力: 以下各项对应的系统能力均为SystemCapability.MiscServices.Pasteb…

2024车载测试还可以冲吗?

2024年已过接近1/4了&#xff0c;你是不是还在围观车载测试行业的发展&#xff1f;同时也在思考着&#xff1a;现在进入车载测试行业还来得及吗&#xff1f;如何高效学习车载测试呢&#xff1f; 我们先来了解一下车载测试行情发展&#xff0c;通过某大平台&#xff0c;我们获取…

解决pycharm安装dlib失败的问题

今天使用pycharm来学习opencv人脸识别库face-recognition的时候出现了一点小问题&#xff0c;在pycharm中直接安装face-recognition会失败&#xff0c;说是因为缺少依赖库dlib&#xff0c;但是直接使用pycharm安装dlib库也有问题&#xff0c;不知道大家遇到没有 错误提示 note…

Avue-data数据大屏显示饼图(附Demo)

目录 前言1. Sql查询2. 颜色细节 前言 对于这部分知识&#xff0c;原先有过柱状图实战&#xff1a;Avue-data数据大屏显示柱状图&#xff08;附Demo讲解&#xff09; 以下直奔主题&#xff0c;以Sql数据库数据为主 1. Sql查询 以饼图为例&#xff0c;需要返回的形式如下&am…

MySQL数据库切换瀚高数据库(PostgreSQL)导致SQL适配问题:BadSqlGrammarException

温馨提示&#xff1a; 下面的出现的情况属于层层递进的&#xff0c;如果只解决其中一种情况会接着报下一个情况&#xff0c;如果只想了解解决方案请直接移步至结论。 1. 情况一&#xff1a;ERROR: operator does not exist: smallint character varying 报错详细描述&#xf…