一文读懂 c++ 容器

容器根据不同的使用场景和需求,有序序列、无序集合以及专门的适配器等各种形式。了解如何根据场景选择合适的容器并使用它们,是写出高效可读性强的 C++ 代码的关键所在,C++ 标准库提供了一系列标准容器来存储和操作数据集合。这些容器被设计为通用、高效且易于使用。它们都是模板类,意味着可以用来存储任何类型的对象! 接下来我们一起了解下关于容器的分类及使用。

    • 序列式容器
      • vector (向量)
          • 案例
          • 使用场景
          • 总结
      • deque (双端队列)
          • 案例
          • 使用场景
          • 总结
      • list (链表)
          • 案例
          • 使用场景
          • 总结
      • forward_list (单向链表)
          • 案例
          • 使用场景
          • 总结
      • array (数组)
          • 案例
          • 使用场景
          • 总结
    • 关联式容器
      • set (集合)
          • 案例
          • 使用场景
          • 总结
      • multiset (多重集合)
          • 案例
          • 使用场景
          • 总结
      • map (映射)
          • 案例
          • 使用场景
          • 总结
      • multimap (多重映射)
          • 案例
          • 使用场景
          • 总结
    • 无序关联式容器
      • unordered_set (无序集合)
          • 案例
          • 使用场景
          • 总结
      • unordered_multiset (无序多重集合)
          • 案例
          • 使用场景
          • 总结
      • unordered_map (无序映射)
          • 案例
          • 使用场景
          • 总结
      • unordered_multimap (无序多重映射)
          • 案例
          • 使用场景
          • 总结
    • 总结

接下来我们一起了解下关于容器的分类及使用。)

序列式容器

vector (向量)

动态数组
用于存储动态大小的数组,提供了快速的随机访问和数组型接口,并能够在运行时动态增长或收缩(尾部添加/删除操作)。

案例
#include <vector>
#include <iostream>int main() {
#if 0std::vector<int> vec = {10, 20, 30};
#else// 初始化一个空的 vectorstd::vector<int> vec;// 添加元素至末尾vec.push_back(10);vec.push_back(20);vec.push_back(30);
#endif// 访问元素std::cout << "First element: " << vec[0] << '\n'; // 使用下标操作符std::cout << "Second element: " << vec.at(1) << '\n'; // 使用 .at() 方法,带边界检查// 获取 vector 的大小std::cout << "The vector size is: " << vec.size() << '\n';// 遍历 vectorfor (size_t i = 0; i < vec.size(); ++i) {std::cout << vec[i] << ' ';}std::cout << '\n';// 使用迭代器遍历for (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << ' ';}std::cout << '\n';// 使用范围基于的 for 循环for (int num : vec) {std::cout << num << ' ';}std::cout << '\n';// 移除最后一个元素vec.pop_back();// 清空 vectorvec.clear();return 0;
}
使用场景
  1. 当你需要一个可以动态改变大小的数组时: std::vector允许在运行时添加和删除元素。因此,如果数据集合的大小不是固定的,使用vector会非常方面。
  2. 当需要频繁访问元素(通过下标),而不需要在中间插入或删除元素时: std::vector提供了对其元素的快速随机访问(时间复杂度为O(1)),但在中间插入或删除操作会导致内部元素的移动,时间复杂度较高(平均为O(n))
  3. 当要求内存连续存储时: std::vector的所有元素都是在一个连续的内存块内存储的,这意味着可以获得数据局部性的优势,并且可以利用指针算术直接访问元素
  4. 在进行大量元素插入或移除操作时,通常在末端操作: 对于std::vector,在末尾添加(push_back())或移除(pop_back())元素效率最高,因为这些操作不需要移动除新增或移除元素之外的任何元素
总结

选择std::vector时应该注意的是,为了支持动态扩展,它可能会在内存中实现多次分配和复制。当vector容量不足以容纳更多元素时,它将进行重新分配,并将所有元素复制到新的内存地址。为了减少这种分配和复制的开销,如果知道大致所需的容量,可以使用reserve()方法预先分配足够的空间。

deque (双端队列)

双端动态数组
允许在容器的两端快速插入和删除对象。与 std::vector 不同的是,std::deque 支持在两端高效地添加或移除元素,非常适合用作队列或双端队列数据结构。

案例
#include <deque>
#include <iostream>int main() {
#if 0std::deque<int> d = { 10, 20 };
#elsestd::deque<int> d;// 在末尾添加元素d.push_back(10);d.push_back(20);
#endif// 在开头添加元素d.push_front(0);d.push_front(-10);// 访问元素std::cout << "First element: " << d.front() << '\n'; // 访问第一个元素std::cout << "Last element: " << d.back() << '\n';   // 访问最后一个元素// 下标访问元素(但不如 std::vector 那么快)std::cout << "Element at index 2: " << d[2] << '\n';// 使用迭代器遍历for (std::deque<int>::iterator it = d.begin(); it != d.end(); ++it) {std::cout << *it << ' ';}std::cout << '\n';// 使用范围基于的 for 循环for (int n : d) {std::cout << n << ' ';}std::cout << '\n';// 删除元素d.pop_front(); // 删除第一个元素d.pop_back();  // 删除最后一个元素return 0;
}
使用场景
  1. 两端操作: 如果你的应用场景需要在容器的两端添加或删除元素,使用 std::deque 是非常合适的。它在两端的插入和删除效率都很高
  2. 作为真正的双端队列(Double-ended queue): std::deque 可被用作队列(先进先出结构)或栈(先进后出结构),因为它提供了一致的接口来操作容器的两端
  3. 大量插入或删除: 如果需要在开始位置频繁插入或删除元素,std::vector 在这种情况下可能会有较差的性能,因为每次都需要移动元素。相比之下,std::deque 在两端插入和删除都有良好的性能
  4. 随机访问: 尽管 std::deque 也提供了随机访问能力,但由于其内部可能是块状链表结构,访问中间元素的效率可能不如 std::vector 那么快。因此,当你需要结合两端插入/删除和不太频繁的随机访问时,std::deque 是一个不错的选择
  5. 作为适配器的基础容器: C++ 标准库中的 stack 和 queue 容器适配器可以使用 std::deque 作为默认的底层容器,尽管 stack 通常用 std::deque(或 std::vector),而 queue 通常专门使用 std::deque,因为 stack 不需要两端操作,而 queue 需要
总结

总的来说,std::deque 在需要灵活操作两端元素的场合表现良好,特别是当你不确定需要的容量大小,并且插入或删除操作在元素集的两端比中间更频繁时,它是一个很好的选择。由于其对两端操作的优化,std::deque 在特定应用场景下,性能可能优于 std::vector。

list (链表)

双向链表
通过双向指针连接各个元素。与数组(如 std::vector)或块状连续存储(如 std::deque)不同,std::list 中的元素在内存中并不连续存放,这使得它非常适合在中间位置进行快速插入和删除操作。

案例
#include <list>
#include <iostream>int main() {// 初始化列表
#if 0std::list<int> mylist = {2, 4, 6, 8};
#elsestd::list<int> mylist;mylist.push_front(6); 

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

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

相关文章

【 文本到上下文 #4】NLP 与 ML

一、说明 欢迎回到我们的 NLP 博客系列&#xff01;当我们进入第四部分时&#xff0c;焦点转移到机器学习 &#xff08;ML&#xff09; 和自然语言处理 &#xff08;NLP&#xff09; 之间的动态相互作用上。在本章中&#xff0c;我们将深入探讨 ML 和 NLP 的迷人协同作用&#…

CGAL::Plane_3<K>平面结构

CGAL::Plane_3<K> 是 CGAL&#xff08;Computational Geometry Algorithms Library&#xff09;中的一个类&#xff0c;代表三维空间中的一个平面。在这个类中&#xff0c;K 是一个内核类型参数&#xff0c;通常代表了一组几何对象的类型和操作&#xff0c;比如点、向量、…

【Linux】Shell 命令以及运行原理

Shell 命令以及运行原理 当用户登录 Linux 系统的时候&#xff0c;系统会给用户创建一个新的进程&#xff0c;一般叫做 bash&#xff08;命令行解释器&#xff09;。 Linux 严格意义上说的是一个操作系统&#xff0c;我们称之为 “核心&#xff08; kernel &#xff09;” &…

如何在 Linux 服务器上设置定时任务?

定时任务&#xff0c;也称为计划任务或cron作业&#xff0c;是在指定的时间间隔内自动执行特定任务的一种方法。在Linux服务器上设置定时任务可以帮助您自动化许多常见的系统管理任务&#xff0c;例如备份数据、清理日志文件、发送通知等。下面是在Linux服务器上设置定时任务的…

Leetcode 3013. Divide an Array Into Subarrays With Minimum Cost II

Leetcode 3013. Divide an Array Into Subarrays With Minimum Cost II 1. 解题思路2. 代码实现 题目链接&#xff1a;3013. Divide an Array Into Subarrays With Minimum Cost II 1. 解题思路 这一题的话思路上的话我一开始是想着偷懒直接用动态规划&#xff0c;结果果然还…

Kafka 问题排查

订单宽表数据不同步 事情的起因是专员在 ze app 上查不到订单了&#xff0c;而订单数据是从 mysql 的 order_search_info 查询的&#xff0c;order_search_info 表的数据是从 oracel 的 BZ_ORDER_INFO 表同步过来的&#xff0c;查不到说明同步有问题 首先重启&#xff0c;同步…

ICMP控制消息 汇总

控制消息由 类型 字段中的值标识。代码 字段给出了消息的附加上下文信息。自协议首次引入以来&#xff0c;一些控制消息已被弃用。 重要的ICMP Control Message控制信息 类型码状态描述0 –回声回复&#xff1a;140回声回复&#xff08;用于ping&#xff09;1和2未分配已预留3 …

0004.电脑开机提示按F1

常用的电脑主板不知道什么原因&#xff0c;莫名其妙的启动不了了。尝试了很多方法&#xff0c;没有奏效。没有办法我就只能把硬盘拆了下来&#xff0c;装到了另一台电脑上面。但是开机以后却提示F1&#xff0c;如下图&#xff1a; 根据上面的提示&#xff0c;应该是驱动有问题…

Spring Security工作原理(三)

在认证之间保存请求 如处理安全异常中所示,当请求没有认证且需要认证资源时,需要保存请求以便在认证成功后重新请求受保护的资源。在Spring Security中,这是通过使用RequestCache实现来保存HttpServletRequest来实现的。 RequestCache HttpServletRequest被保存在Request…

可替代Allegro A3901的国产GC3901 5V H 桥驱动器,驱动电流能力更强,且低成本,大电流

步进电机驱动的应用方案目前市场上大多选用国外品牌的电机驱动器&#xff0c;其中ALLEGRO的A3901在这一块的应用很广泛。但是由于市场越来越成熟&#xff0c;当前对于产品开发成本要求也越来越低&#xff0c;国产品牌也推出了相应的镜头驱动器&#xff0c;因此ALLEGRO的A3901已…

Redis和RediSearch的安装及使用

1. 安装要求 ReadiSearch要求Redis的版本在6.0以上RediSearch 要求使用 GNU Make 4.0 或更高版本 2. Redis的安装 查看redis的版本&#xff1a; redis-server --version或者&#xff0c;如果你已经启动了Redis服务器&#xff0c;你也可以使用redis-cli工具来获取版本信息&a…

Win10/11中VMware Workstation设置网络桥接模式

文章目录 一、添加VMware Bridge Protocol服务二、配置桥接参数1.启用系统Device Install Service服务2.配置VMware 需要确认物理网卡是否有添加VMware Bridge Protocol服务 添加VMware Bridge Protocol服务 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参…

枚举类型有着一篇足以

✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;橘橙黄又青-CSDN博客 1.关键字enum的定义 enum是C语言中的一个关键字&#xff0c;enum叫枚举数据类型&#…

helm 一键部署

helm HPA rancher 安全机制 k8s的核心功能&#xff1a;组件功能 k8s的网络 命令行基本的增删改查 deployment statefulsets 挂载卷&#xff1a;emptyDir&#xff0c; hostPath&#xff0c; nfs pv pvc 动态pvc必问 configmap ingress hpa pod 的自动伸缩 helm 什么是hel…

python opencv 图片缺陷检测(讲解直方图以及相关系数对比法)

一、利用直方图的方式进行批量的图片缺陷检测&#xff08;方法简单&#xff09; 二、步骤&#xff08;完整代码见最后&#xff09; 2.1灰度转换&#xff08;将原图和要检测对比的图分开灰度化&#xff09; 灰度化的作用是因为后面的直方图比较需要以像素256为基准进行相关性比…

Vue2中CesiumV1.113.0加载离线地图

Vue2中CesiumV1.113.0加载离线地图&#xff0c;本文以天地图为例。 1.使用nodejs获取天地图 新建nodejsdownmap项目文件夹&#xff0c;初始化项目 npm init -y src/index.js // An highlighted block var Bagpipe require(bagpipe) var fs require("fs"); var r…

2024.1.21周报

目录 摘要 ABSTRACT 一、文献阅读 一、题目 二、摘要 三、Introduction 四、模型 一、连续时间模型 二、离散时间模型 五、结论 二、实验代码 Navier–Stokes equation 总结 摘要 本周我阅读了一篇题目为Physics-informed neural networks: A deep learning fra…

快速傅立叶变换FFT学习笔记

什么是FFT&#xff1f; FFT&#xff08;Fast Fourier Transformation&#xff09; 是离散傅氏变换&#xff08;DFT&#xff09;的快速算法&#xff0c;即快速傅氏变换。FFT使计算机计算离散傅里叶变换所需要的乘法次数大为减少&#xff0c;特别是被变换的抽样点数N越多&#x…

图像数据增广

目录 一、常用的图像增广方法 1、随机翻转 2、随机裁剪 3、随机颜色变换 二、图像代码实现 1、定义图像显示辅助函数 2、随机翻转 3、随机裁剪 4、随机颜色变换 5、结合多种图像增广方法 三、使用图像增广进行训练 1、下载数据集 2、读取图像并增广 3、多GPU训练 …

vue2面试题:对vue生命周期的理解

vue2面试题&#xff1a;对vue生命周期的理解 回答思路:生命周期是什么-->生命周期有哪些-->生命周期的总体流程-->数据请求在created和mouted的区别生命周期是什么生命周期有哪些生命周期的总体流程beforeCreate-->created:created&#xff1a;created-->before…