掌握C++11标准库(STL):理解STL的核心概念

深入探索C++11标准库STL:新特性和优化技巧

  • 一、前言
  • 二、容器简介
  • 三、迭代器简介
  • 四、map与unordered_map(红黑树VS哈希表)
    • 4.1、map和unordered_map的差别
    • 4.2、优缺点以及适用处
    • 4.3、小结
  • 五、总结

一、前言

STL定义了强大的、基于模板的、可复用的组件,实现了许多通用的数据结构及处理这些数据结构的算法。其中包含三个关键组件——容器(container,流行的模板数据结构)、迭代器(iterator)和算法(algorithm)。

组件描述
容器容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。
迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。
算法算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。

二、容器简介

STL容器,可将其分为四类:序列容器、有序关联容器、无序关联容器、容器适配器。

序列容器:

标准库容器类描述
array固定大小,直接访问任意元素
deque从前部或后部进行快速插入和删除操作,直接访问任何元素
forward_list单链表,在任意位置快速插入和删除
list双向链表,在任意位置进行快速插入和删除操作
vector从后部进行快速插入和删除操作,直接访问任意元素
Sequence Containers
vector
list
deque
array
forward_list

有序关联容器(键按顺序保存):

标准库容器类描述
set快速查找,无重复元素
multiset快速查找,可有重复元素
map一对一映射,无重复元素,基于键快速查找
multimap一对一映射,可有重复元素,基于键快速查找
Associative Containers
Set
Map
Multiset
Multimap

无序关联容器:

标准库容器类描述
unordered_set快速查找,无重复元素
unordered_multiset快速查找,可有重复元素
unordered_map一对一映射,无重复元素,基于键快速查找
unordered_multimap一对一映射,可有重复元素,基于键快速查找
Unordered Containers
Unordered_set
Unordered_map
Unordered_multiset
Unordered_multimap

容器适配器:

标准库容器类描述
stack后进先出(LIFO)
queue先进先出(FIFO)
priority_queue优先级最高的元素先出

序列容器描述了线性的数据结构(也就是说,其中的元素在概念上” 排成一行"), 例如数组、向量和 链表。

关联容器描述非线性的容器,它们通常可以快速锁定其中的元素。这种容器可以存储值的集合或 者键-值对。

栈和队列都是在序列容器的基础上加以约束条件得到的,因此STL把stack和queue作为容器适配器来实现,这样就可以使程序以一种约束方式来处理线性容器。类型string支持的功能跟线性容器一样, 但是它只能存储字符数据。

三、迭代器简介

迭代器在很多方面与指针类似,也是用于指向首类容器中的元素(还有一些其他用途,后面将会提
到)。 迭代器存有它们所指的特定容器的状态信息,即迭代器对每种类型的容器都有一个实现。 有些迭代器的操作在不同容器间是统一的。 例如,运算符间接引用一个迭代器,这样就可以使用它所指向的元素。++运算符使得迭代器指向容器中的下一个元素(和数组中指针递增后指向数组的下一个元素类似)。

STL 首类容器提供了成员函数begin end。函数 begin 返回一个指向容器中第一个元素的迭代器,函数 end 返回一个指向容器中最后一个元素的下一个元素(这个元素并不存在,常用于判断是否到达了容器的结束位位置)的迭代器。 如果迭代器 it 指向一个特定的元素,那么 ++it 指向这个元素的下一个元素。*it 指代的是it指向的元素。 从函数 end 中返回的迭代器只在相等或不等的比较中使用,来判断这个“移动的迭代器” (在这里指it)是否到达了容器的末端。

使用一个 iterator 对象来指向一个可以修改的容器元素,使用一个 const_iterator 对象来指向一个不能修改 的容器元素。

类型描述
随机访问迭代器(random access)在双向迭代器基础上增加了直接访问容器中任意元素的功能, 即可以向前或向后跳转任意个元素
双向迭代器(bidirectional)在前向迭代器基础上增加了向后移动的功能。支持多遍扫描算法
前向迭代器(forword)综合输入和输出迭代器的功能,并能保持它们在容器中的位置(作为状态信息),可以使用同一个迭代器两次遍历一个容器(称为多遍扫描算法)
输出迭代器(output)用于将元素写入容器。 输出迭代楛每次只能向前移动一个元索。 输出迭代器只支持一遍扫描算法,不能使用相同的输出迭代器两次遍历一个序列容器
输入迭代器(input)用于从容器读取元素。 输入迭代器每次只能向前移动一个元素。 输入迭代器只支持一遍扫描算法,不能使用相同的输入迭代器两次遍历一个序列容器

每种容器所支持的迭代器类型决定了这种容器是否可以在指定的 STL 算 法中使用。 支持随机访问迭代器的容器可用于所有的 STL 算法(除了那些需要改变容器大小的算法,这样的算法不能在数组和 array对象中使用)。 指向 数组的指针可以代替迭代器用于几乎所有的 STL 算法中,包括那些要求随机访问迭代器的算法。

Bidirectional Iterator
Random Access Iterator
Forward Iterator
Input Iterator
Output Iterator

下表显示了每种 STL 容器所支持的迭代器类型。 注意, vector 、 deque 、 list 、 set、 multiset 、 map 、 multimap以及 string 和数组都可以使用迭代器遍历。

容器支持的迭代器类型容器支持的迭代器类型
vector随机访问迭代器set双向迭代器
array随机访问迭代器multiset双向迭代器
deque随机访问迭代器map双向迭代器
list双向迭代器multimap双向迭代器
forword_list前向迭代器unordered_set双向迭代器
stack不支持迭代器unordered_multiset双向迭代器
queue不支持迭代器unordered_map双向迭代器
priority_queue不支持迭代器unordered_multimap双向迭代器

下表显示了在 STL容器的类定义中出现的几种预定义的迭代器 typedef。不是每种 typedef 都出现在每个容器中。 我们使用常量版本的迭代器来访问只读容器或不应该被更改的非只读容器,使用反向迭代器来以相反的方向访问容器。

为迭代器预先定义的typedef++的方向读写能力
iterator向前读/写
const_iterator向前
reverse_iterator向后读/写
const_reverse_iterator向后

下表显示了可作用在每种迭代器上的操作。 除了给出的对于所有迭代器都有的运算符,迭代器还必须提供默认构造函数、拷贝构造函数和拷贝赋值操作符。 前向迭代器支持++ 和所有的输入和输出迭代器的功能。 双向迭代器支持–操作和前向迭代器的功能。 随机访问迭代器支持所有在表中给出的操作。 另外, 对于输入迭代器和输出迭代器,不能在保存迭代器之后再使用保存的值。

适用所有迭代器的操作描述
++p前置自增迭代器
p++后置自增迭代器
p=p1将一个迭代器赋值给另一个迭代器
输入迭代器描述
*p间接引用一个迭代器
p->m使用迭代器读取元素m
p==p1比较两个迭代器是否相等
p!=p1比较两个迭代器是否不相等
输出迭代器描述
*p间接引用一个迭代器
p=p1把一个迭代器赋值给另一个

前向迭代器:前向迭代器提供了输入和输出迭代器的所有功能。

双向迭代器描述
–pq
p–后置自减迭代器
随机访问迭代器描述
p+=i迭代器p前进i个位置
p-=i迭代器p后退i个位置
p+i在迭代器p 的位置上前进i个位置
p-i在迭代器p的位置上后退i个位置
p-p1表达式的值是一个整数,它代表同一个容器中两个元素间的距离
p[i]返回与迭代器p的位置相距i的元素
p<p1若迭代器p小于p1(即容器中p在p1前)则返回 true, 否则返回 false
p<=p1若迭代器p小千或等于p1 (即容器中p 在p1前或位咒相同)则返回 true, 否则返回 false
p>p1若迭代器p 大于p1(即容器中p在p1后)则返回true, 否则返回false
p>=p1若迭代器p大于或等于p1(即容楛中p在p1后或位置相同)则返回 true, 否则返回 false

四、map与unordered_map(红黑树VS哈希表)

C++11 增加了无序容器 unordered_map/unordered_multimap 和unordered_set/unordered_multiset,由于这些容器中的元素是不排序的,因此,比有序容器map/multimap 和 set/multiset 效率更高。 map 和 set 内部是红黑树,在插入元素时会自动排序,而无序容器内部是散列表( Hash Table),通过哈希( Hash),而不是排序来快速操作元素,使得效率更高。由于无序容器内部是散列表,因此无序容器的 key 需要提供 hash_value 函数,其他用法和map/set 的用法是一样的。不过对于自定义的 key,需要提供 Hash 函数和比较函数。

4.1、map和unordered_map的差别

(1)需要引入的头文件不同。

  • map: #include <map>
  • unordered_map: #include <unordered_map>

(2)内部实现机理不同。

  • map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜
    索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点
    都代表着map的一个元素。
  • unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到
    Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应
    用)。因此,其元素的排列顺序是无序的。

4.2、优缺点以及适用处

map:

  1. 优点:有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
    红黑树,内部实现一个红黑书使得map的很多操作在log n 的时间复杂度下就可以实现,因此效率非常的高。
  2. 缺点:空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间。
  3. 适用处:对于那些有顺序要求的问题,用map会更高效一些。

unordered_map:

  1. 优点: 因为内部实现了哈希表,因此其查找速度非常的快。
  2. 缺点: 哈希表的建立比较耗费时间。
  3. 适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map。

4.3、小结

  1. 内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。
  2. 但是unordered_map执行效率要比map高很多。
  3. 对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的。

五、总结

C++ 参考手册,重点学习C++11起的容器。
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

边缘智能网关在智慧大棚上的应用突破物联网大关

边缘智能网关在智慧大棚上的应用&#xff0c;是现代农业技术的一大突破。通过与农作物生长模型的结合&#xff0c;边缘智能网关可以根据实时的环境数据和历史数据&#xff0c;预测农作物的生长趋势和产量&#xff0c;提供决策支持和优化方案。这对于农民来说&#xff0c;不仅可…

使用STM32 HAL库实现RS232串口通信的步骤和技巧

本文将介绍如何使用STM32 HAL库来实现RS232串口通信&#xff0c;包括步骤、API函数的调用方法和一些技巧。具体将讨论串口配置、发送和接收数据的方法&#xff0c;并提供相关示例代码。 引言&#xff1a; STM32 HAL库为嵌入式系统提供了简化和标准化的编程接口&#xff0c;方便…

Unity坦克大战开发全流程——结束场景——通关界面

结束场景——通关界面 就照着这样来拼 写代码 hideme不要忘了 修改上一节课中的代码

HCIP:rip综合实验

实验要求&#xff1a; 【R1-R2-R3-R4-R5运行RIPV2】 【R6-R7运行RIPV1】 1.使用合理IP地址规划网络&#xff0c;各自创建环回接口 2.R1创建环回 172.16.1.1/24 172.16.2.1/24 172.16.3.1/24 3.要求R3使用R2访问R1环回 4.加快网络收敛&#xff0c;减少路由条目数量&#xff0c;增…

5G随身WiFi避坑,5G随身WiFi口碑推荐,5G随身WiFi避雷,5G随身WiFi好用吗?

第一、切忌盲目入坑&#xff0c;目前市面上的主流随身 WiFi都是4G网络&#xff0c;不支持5G&#xff0c;当一些只卖几十块的随身WiFi&#xff0c;商家告诉你是5G随身WiFi的时候&#xff0c;直接拉黑。随身WiFi芯片都上百了&#xff0c;设备才几十块&#xff0c;怎么可能&#x…

5 个顶级的免费磁盘分区软件工具评测分享

磁盘分区可能是一个脆弱而复杂的过程&#xff0c;磁盘崩溃或用户设备受到病毒攻击的风险很高。因此&#xff0c;它们很难由用户单独或手动管理。本文详细介绍了可以帮助简化磁盘分区过程的不同软件工具、它们的功能和优点。那么让我们开始吧。 什么是磁盘分区工具&#xff1f;…

Apollo自动驾驶:改变交通运输的游戏规则

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 ChatGPT体验地址 文章目录 前言1. Apollo缓存层2. 本地状态管理库3. 离线同步和冲突解决4. 离线数据同步和离线优先策略结论 &#x1f4f2;&#x1f50c; 构建离线应用&#xff1a;Apollo…

Mediapipe绘制实时3d铰接骨架图——Mediapipe实时姿态估计

一、前言 大约两年前&#xff0c;基于自己的理解我曾写了几篇关于Mediapipe的文章&#xff0c;似乎帮助到了一些人。这两年&#xff0c;忙于比赛、实习、毕业、工作和考研。上篇文章已经是一年多前发的了。这段时间收到很多私信和评论&#xff0c;请原谅无法一一回复了。我将尝…

《数据库开发实践》之触发器【知识点罗列+例题演练】

一、什么是触发器&#xff1f; 1.概念&#xff1a; 简单来说触发器就是一种特殊的存储过程&#xff0c;在数据库服务器触发事件的时候会自动执行其SQL语句集。 2.构成四要素&#xff1a; &#xff08;1&#xff09;名称&#xff1a;要符合标识符命名规则 &#xff08;2&am…

IPD-PDP产品开发流程-PDT产品开发计划Charter文档模板(word)4

今天继续为您分享PDT的产品开发计划Charter模板的内容。 Charter任务书模板内容9&#xff1a;资料开发计划 在IPD运作时&#xff0c;配套资料的开发也是非常重要的内容&#xff0c;尤其是产品发布、上市的时候需要配套的产品资料包非常全面&#xff0c;所以在Charter中也要列出…

亚马逊云科技Amazon Q,一款基于生成式人工智能的新型助手

近日&#xff0c;亚马逊云科技宣布推出Amazon Q&#xff0c;这是一款基于生成式人工智能&#xff08;AI&#xff09;的新型助手&#xff0c;专为辅助工作而设计&#xff0c;可以根据您的业务量身定制。通过连接到公司的信息存储库、代码、数据和企业系统&#xff0c;可以使用Am…

leetcode 贪心(分发糖果、K次取反后最大化的数组和、加油站)

1005.K次取反后最大化的数组和 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&#xff09; 以这种方式修改数组后…