C++STL细节,底层实现,面试题04
文章目录
- 19. STL
- 19.1. 序列容器
- 19.1.1. vector
- 19.1.1.1. 底层实现和特点
- 19.1.1.2. 常用函数
- 19.1.1.3. emplace_back() vs push_back()
- 19.1.2. array
- 19.1.2.1. 底层实现和特点
- 19.1.2.2. 常用函数
- 19.1.3. deque
- 19.1.3.1. 底层实现和特点
- 19.1.3.2. 常用函数
- 19.1.4 list
- 19.1.4.1. 底层实现和特点
- 19.1.4.2. 常用函数
- 19.2. 关联容器
- 19.2.1. map
- 19.2.1.1. 底层实现和特点
- 19.2.1.2. 常用函数
- 19.2.1.3. map vs unordered_map
- 19.2.2. set
- 19.2.2.1. 底层实现和特点
- 19.2.2.2. 常用函数
- 19.2.2.3. set vs unordered_set
- 19.2.3 自定义比较函数对象,来定义元素的比较方式。
- 19.3. 容器适配器
- 19.3.1 queue
- 19.3.1.1. 底层实现和特点
- 19.3.1.2. 常用函数
- 19.3.2 priority_queue
- 19.3.2.1. 底层实现和特点
- 19.3.2.2. 常用函数
- 19.3.3 stack
- 19.3.3.1. 底层实现和特点
- 19.3.3.2. 常用函数
19. STL
C++标准库容器,官方文档https://learn.microsoft.com/zh-cn/cpp/standard-library/stl-containers?view=msvc-170
19.1. 序列容器
可顺序访问元素。
19.1.1. vector
19.1.1.1. 底层实现和特点
- 底层实现为动态数组(使用数组指针),动态分配空间。连续内存空间,支持随机访问。
- 它通过下标访问元素,时间复杂度o(1)。
- 尾部插入和删除操作,时间复杂度o(1)。
- 其余部分插入和删除,需要移动元素,时间复杂度o(n)。
- 当内存空间不足时,会重新分配内存空间,扩充为原来的两倍,并拷贝原有数据。
- 应用场景:适用于需要随机访问或频繁在序列尾部进行操作的场景。
19.1.1.2. 常用函数
- front() 返回第一个元素的引用。
- back() 返回最后一个元素的引用。
- begin() 返回第一个元素的迭代器。
- end() 返回超过末尾迭代器。
- clear() 清空。
- empty() 判空。
- emplace_back() 将就地构造的元素添加到末尾。
- push_back() 将元素添加到末尾。
- pop_back() 删除末尾元素。
- erase(position),erase(first,end) 删除元素。
- insert(positon,value) 添加元素。
- swap()交换容器元素。
- resize(size),resize(size,value) 指定新的大小。
19.1.1.3. emplace_back() vs push_back()
-
emplace_back()的参数会使用forward<>完美转发给构造函数,然后在容器提供的位置就地构造。即只构造一次,如下图。
-
push_back()的参数作为右值传入,先构造元素,再移动到末尾,即先调用构造函数,然后调用移动构造函数,如下图。
-
【注意】 emplace_back()的参数 {1,2} 会自动转换成initializer_list并进行完美转发,但vector并没有initializer_list的构造函数,所以报错。
vector<pair<int, int>> v;v.push_back({1,2});v.emplace_back({1,2}); //报错
19.1.2. array
19.1.2.1. 底层实现和特点
- 底层实现为数组,固定大小。连续内存空间,支持随机访问。
19.1.2.2. 常用函数
- fill() 替换所有的元素。
- swap() 交换容器元素。
19.1.3. deque
19.1.3.1. 底层实现和特点
- 底层实现为中控器+缓冲区+迭代器。
- 中控器,将分段连续的内存空间链接起来,才能在逻辑上连续,支持随机访问。使用指针数组,存放缓存区的地址。
- 迭代器,四个指针。
- T* cur,指向缓冲区的当前元素。
- T* first,指向缓冲区的头。
- T* last,指向缓存区的尾(含备用空间)。
- T** node,指向管控中心,即缓冲区的标记位置。
- 双端队列,首尾两端进行动态增删。
- 相比vector和list,deque不适合遍历,因为每次访问元素,都要检查是否到达了内存片段的边界,造成了额外开销。
- 应用场景:适用于需要频繁在序列两端进行操作的场景。
19.1.3.2. 常用函数
- emplace_back() 将就地构造的元素添加到末尾。
- emplace_front() 将就地构造的元素添加到开头。
- push_back() 将元素添加到末尾。
- push_front() 将元素添加到开头。
- pop_back() 删除末尾元素。
- pop_front() 删除开头元素。
- swap() 交换容器元素。
19.1.4 list
19.1.4.1. 底层实现和特点
- 底层实现为双链表,动态分配内存。离散内存空间,不支持随机访问。
- 通过指针访问元素,需要遍历直至要访问的元素,时间复杂度o(n)。
- 支持在任意位置快速插入和删除操作,时间复杂度o(1)。
- 支持双向遍历。
- 内存空间的使用效率并不高,一来它存放在离散而非连续的内存空间;二来它需要消耗更多内存空间来保存元素之间的关联信息。
- 应用场景:适用于需要频繁在任意位置进行操作,但不需要随机访问的场景。
19.1.4.2. 常用函数
- emplace_back() 将就地构造的元素添加到末尾。
- emplace_front() 将就地构造的元素添加到开头。
- push_back() 将元素添加到末尾。
- push_front() 将元素添加到开头。
- pop_back() 删除末尾元素。
- pop_front() 删除开头元素。
- remove() 删除指定值。
- reverse() 反转元素。
- sort() 按升序排序,sort( greater<>() ) 按降序排序。
- swap() 交换容器元素。
- rbegin() 返回反向第一个元素的迭代器。
- rend() 返回反向超过末尾迭代器。
19.2. 关联容器
通过key访问元素。
19.2.1. map
19.2.1.1. 底层实现和特点
- 底层实现为红黑树,有序。
- 应用场景:适用于需要通过key快速查找value的场景。
19.2.1.2. 常用函数
- contains() (C++20)是否包含指定键的元素。
- count() 是否包含指定键的元素。
- emplace() 就地插入构造的元素,即不执行复制或移动操作。
- find() 返回指定键的迭代器。
- erase(key),erase(iter_position) 移除指定键或指定位置的元素。
- lower_bound() 返回键值等于或大于指定键的第一个元素的迭代器。
- upper_bound() 返回键值大于指定键的第一个元素的迭代器。
19.2.1.3. map vs unordered_map
- 底层实现为哈希表,无序。
- 应用场景:适用于需要通过key快速查找value的场景,但不关心key的顺序。
- unordered_map 直接访问元素的速度更快,尤其在大规模时,因为它通过直接计算key的哈希值来访问元素,时间复杂度o(1)。
- 但unordered_map 内存占用更高,因为底层的哈希表需要预分配足够的空间。
19.2.2. set
19.2.2.1. 底层实现和特点
- 底层实现为红黑树,有序。
- 元素自身就是key。
- 元素有唯一性,不允许出现重复的元素,且元素不可更改,但可以插入或删除。
- 应用场景:适用于需要快速查找和去重的场景。
19.2.2.2. 常用函数
- contains() (C++20)是否包含指定键的元素。
- count() 是否包含指定键的元素。
- emplace() 就地插入构造的元素,即不执行复制或移动操作。
- find() 返回指定键的迭代器。
- erase(key),erase(iter_position) 移除指定键或指定位置的元素。
- lower_bound() 返回键值等于或大于指定键的第一个元素的迭代器。
- upper_bound() 返回键值大于指定键的第一个元素的迭代器。
19.2.2.3. set vs unordered_set
- 底层实现为哈希表,无序。
- 应用场景:适用于需要快速查找和去重的场景,但不关心元素的顺序。
- unordered_set 直接访问元素的速度更快,尤其在大规模时,因为它通过直接计算key的哈希值来访问元素,时间复杂度o(1)。
- 但unordered_set 内存占用更高,因为底层的哈希表需要预分配足够的空间。
19.2.3 自定义比较函数对象,来定义元素的比较方式。
#include<iostream>
#include<set>
using namespace std;// 自定义比较函数对象,按照 pair 的第二个值进行比较
struct CompareBySecond {bool operator()(const pair<int, int>& p1, const pair<int, int>& p2) const {return p1.second < p2.second;}
};int main()
{set<pair<int, int>, CompareBySecond> s = { {1,20},{2,10},{3,30},{4,5} };for (auto&& u : s)cout << u.first << " " << u.second << endl;return 0;
}
19.3. 容器适配器
本身只是一个封装层,必须依赖指定的底层容器,才能实现具体功能。即它是序列容器或关联容器的变体。
19.3.1 queue
19.3.1.1. 底层实现和特点
- 底层容器默认deque。
- 队列,先进先出。
- 应用场景:适用于需要先进先出操作的场景,如广度优先搜索、任务调度、数据缓冲区等。
19.3.1.2. 常用函数
- front() 返回第一个元素的引用。
- back() 返回最后一个元素的引用。
- empty() 返回是否空。
- pop() 头部移除元素。
- push() 尾部添加元素。
- size() 返回元素数量。
19.3.2 priority_queue
19.3.2.1. 底层实现和特点
- 底层容器默认vector。
- 优先队列,元素按照优先级排序,每次弹出最高优先级的元素,即默认最大堆。
- 最小堆使用 greater<> 作比较器。
- 应用场景:适用于需要按照优先级处理元素的场景,如任务调度、最大(小)堆实现等。
19.3.2.2. 常用函数
- top() 返回顶部元素的常量引用,即返回值不是左值。
- empty() 返回是否空。
- pop() 顶部移除元素,即弹出最大元素。
- push() 添加元素。
- size() 返回元素数量。
19.3.3 stack
19.3.3.1. 底层实现和特点
- 底层容器默认deque。
- 栈,后进先出。
- 不允许遍历,只能访问顶部元素。
- 应用场景:适用于需要后进先出操作的场景,如深度优先搜索、表达式求值、括号配对等。
19.3.3.2. 常用函数
- top() 返回顶部元素的引用。
- empty() 返回是否空。
- pop() 顶部移除元素。
- push() 顶部添加元素。
- size() 返回元素数量。
相关文章:

C++STL细节,底层实现,面试题04
文章目录 19. STL19.1. 序列容器19.1.1. vector19.1.1.1. 底层实现和特点19.1.1.2. 常用函数19.1.1.3. emplace_back() vs push_back() 19.1.2. array19.1.2.1. 底层实现和特点19.1.2.2. 常用函数 19.1.3. deque19.1.3.1. 底层实现和特点19.1.3.2. 常用函数 19.1.4 list19.1.4.…...

Linux查看Oracle数据库的环境变量
Linux查看Oracle数据库的环境变量 在Linux上查看Oracle数据库的环境变量,通常涉及检查当前shell会话中已设置的环境变量。这些环境变量可能包括ORACLE_HOME、ORACLE_SID、PATH(可能包含Oracle二进制文件的路径)等。 以下是几种方法来查看这…...

pg数据库学习知识要点分析-1
知识要点1 对象标识OID 在PostgreSQL内部,所有的数据库对象都通过相应的对象标识符(object identifier,oid)进行管理,这些标识符是无符号的4字节整型。数据库对象与相应oid 之间的关系存储在对应的系统目录中…...

【Web】CTFSHOW 七夕杯 题解
目录 web签到 easy_calc easy_cmd web签到 CTF中字符长度限制下的命令执行 rce(7字符5字符4字符)汇总_ctf中字符长度限制下的命令执行 5个字符-CSDN博客7长度限制直接梭了 也可以打临时文件RCE import requestsurl "http://4ae13f1e-8e42-4afa-a6a6-1076acd08211.c…...

react native 设置屏幕锁定
原生配置 android 在android/app/src/main/AndroidManifest.xml在这个文件里的入口activity里添加 android:screenOrientation"portrait" <activityandroid:name".MainActivity"android:label"string/app_name" …...

探索 IPv6 协议:互联网的新一代寻址
目录 一.概述 IPv4 的问题和 IPv6 的新特性 IPv6 协议体系 二.IPv6 寻址架构:巨大的地址空间与灵活的寻址模式 IPv6 寻址概述 地址表示方法 地址前缀与地址类型标识 单播地址 任播地址 多播地址 特殊的 IPv6 地址 IPv6 主机与路由器寻址 地址分配 三.I…...

Ubuntu意外断电vmdk损坏--打不开磁盘“***.vmdk”或它所依赖的某个快照磁盘。
背景:电脑资源管理器崩溃卡死,强行断电重启,结果虚拟机打不开了,提示打不开磁盘“***.vmdk”或它所依赖的某个快照磁盘。 删除lck文件:失败vmware-vdiskmanager修复 :提示无法修复最终用 VMFS Recovery挂载…...

202466读书笔记|《一天一首古诗词》——借问梅花何处落,风吹一夜满关山
202466读书笔记|《一天一首古诗词》——借问梅花何处落,风吹一夜满关山 上册下册 《一天一首古诗词》作者李锡琴,蛮早前加入书架的已购买书籍,这次刚好有点时间,利用起来读完。 赏析没有细看,只读了诗词部分࿰…...

如何调用本地ollama的http请求接口
http://127.0.0.1:11434/api/generate 使用http post请求,参数 { "model": "qwen", "prompt": "为什么天空是蓝色?", "stream": false } 返回结果如下: {"model": "qwen",…...

【C】190 颠倒二进制位
颠倒给定的 32 位无符号整数的二进制位。 提示: 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因…...

蓝桥杯备战5.图书管理员
[NOIP2017]图书管理员 (nowcoder.com) #include<bits/stdc.h> #define endl \n #define int long long using namespace std; const int N 2e510,M1e310; int a[N]; int n,q; int check(int l,int x) {int tmppow(10,l);for(int i1;i<n;i){if(a[i]%tmpx){cout<&…...

微型显示器可以实时监测大脑活动
美国团队开发基于LED的设备,以可视化大脑活动,在脑外科手术中指导神经外科医生 来自加州大学圣地亚哥分校和马萨诸塞州总医院的工程师和医生开发了一种薄膜显示设备,该设备结合了电极网格和特殊的GaN LED,可以在手术过程中实时跟…...

移动端适配方案
移动端适配 方案 1:rem html font-size 方案 2:vw rem html font-size rem 是相对于 html 元素的 font-size 来设置的单位,通过在不同屏幕尺寸下动态修改 html 元素的 font-size 可达到适配效果 在开发中,我们只需要考虑两个…...

【Ajax零基础教程】-----第一课 Ajax简介
一、什么是ajax ajax即 Asynchronous javascript And XML (异步 javaScript 和 XML) 是一种创建交互式,快速动态应用的网页开发技术,无需重新加载整个网页的情况下,能够更新页面局部数据的技术。 二、为什么使用Ajax 通过在后台与服务器进行少…...

大型医疗挂号微服务“马上好医”医疗项目(5)Swagger的使用
Swagger的简单介绍 Swagger 是一个 RESTful 接口文档的规范和工具集,它的目标是统一 RESTful 接口文档的格式和规范。在开发过程中,接口文档是非常重要的一环,它不仅方便开发者查看和理解接口的功能和参数,还能帮助前后端开发协同…...

C语言从头学04——介绍占位符和输出格式
占位符、输出格式都是与 printf() 相关的,当然其它函数也有用到占位符的。这里先介绍它们在 printf() 的使用。 一、先介绍占位符,所谓“占位符”通俗讲就是先占个位置,后边再找具体值(参数)代入进行显示的一种方法。先用一个例子说明…...

写爬虫代码抓取Asterank中小行星数据
2024年5月4日 问题来源 解决方案 回顾2023年7月14日自己写的爬虫代码 import requests import re import pandas as pd texts[] def getData(page):#每页评论的网址urlhttps://item.jd.com/51963318622.html#comment#添加headers,伪装成浏览器headers{User-Agent:…...

leetCode81. 搜索旋转排序数组 II
leetCode81. 搜索旋转排序数组 II 题目思路 可以二分后的具体思路见我的上篇博客 搜索旋转排序数组 代码 class Solution { public:bool search(vector<int>& nums, int target) {if(nums.empty()) return false;int R nums.size() - 1;while(R > 0 &&…...

在Ubuntu上怎么查看安装了哪些包?
2024年5月3日,周五晚上 在Ubuntu上,你可以使用以下命令来查看系统中已安装的包: 使用dpkg命令:dpkg --list这个命令将列出系统中所有已安装的软件包,包括名称、版本号和描述等信息。你可以使用 grep 命令来过滤结果&a…...

Navicat连接远程数据库时,隔一段时间不操作出现的卡顿问题
使用 Navicat 连接服务器上的数据库时,如果隔一段时间没有使用,再次点击就会出现卡顿的问题。 如:隔一段时间再查询完数据会出现: 2013 - Lost connection to MySQL server at waiting for initial communication packet, syste…...

修改页签标题 + 页签图表
修改图标 在App.vue下的created()里或者路由守卫中输入 var link document.querySelector("link[rel*icon]") || document.createElement("link"); link.type "image/x-icon"; link.rel "shortcut icon"; link.href require(l…...

QT---day5,通信
1、思维导图 2、TCp 服务器 #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include <QTcpServer> #include <QList> #include <QTcpSocket> #include <QMessageBox> #include <QDebug> #include <QTcpServer> QT_B…...

设计模式: 工厂模式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。 工厂模式属于创建型…...

Java 多线程补充
线程池 Java线程池是一种能够有效管理线程资源的机制,它可以显著提高应用性能并降低资源消耗。 线程池的主要优点包括: 资源利用高效:通过重用已存在的线程,减少了频繁创建和销毁线程带来的系统开销。响应速度提升:…...

【Java基础】Maven继承
1. 前言 Maven 在设计时,借鉴了 Java 面向对象中的继承思想,提出了 POM 继承思想。 2. Maven继承 当一个项目包含多个模块时,可以在该项目中再创建一个父模块,并在其 POM 中声明依赖,其他模块的 POM 可通过继承父模…...

java技术总结
1.java基本数据类型? byte 1,short 2 ,int 4,long 8 ,float 4,double 8,boolean 1,char 2 2.java为什么要有包装类型? 前 6 个类派生于公共的超类 Number,而 Character 和 Boolean 是 Object 的直接子类。 被 final 修饰, Java 内置的包装类是无法被继承的。 包装…...

C# WinForm —— 12 ListBox绑定数据
ListBox加载大量数据时,避免窗体闪烁的方法: 在加载语句的前后分别加上 BeginUpdate()方法 和 EndUpdate()方法 指定一个集合为绑定的数据源 1. 首先,右键项目,添加类 2. 在新建的类文件中添加属性值信息 3. 构建初始化的对象…...

自动驾驶主流芯片及平台架构(二)特斯拉自动驾驶芯片平台介绍
早期 对外采购mobileye EyeQ3 芯片摄像头半集成方案,主要是为了满足快速量产需求,且受制于研发资金不足限制; 中期 采用高算力NVIDIA 芯片平台其他摄像头供应商的特斯拉内部集成方案,mobileye开发节奏无法紧跟特斯拉需求ÿ…...

powershell@管道符过滤的顺序问题@powershell管道符如何工作
文章目录 select 和 where谁先执行powershell管道符stop-service 为例查看文档中的典型参数介绍stop-process为例介绍管道符传参是怎么工作的Id参数InputObject 参数Name参数额外的试验反面例子应用:get-process 和stop-process配合 select 和 where谁先执行 在执行筛选时&…...

SMI接口
目录 SMI 接口帧格式读时序写时序 IP 设计IP 例化界面IP 接口IP 验证 SMI 接口 SMI(Serial Management Interface)串行管理接口,也被称作 MII 管理接口(MII Management Interface),包括 MDC 和 MDIO 两条信…...