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() 返回元素数量。

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

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

相关文章

誉天教育近期开班计划

云计算HCIE 晚班 2024/5/13 大数据直通车 周末班 2024/5/25 数通直通车 晚班 2024/5/27 云服务HCIP 周末班 2024/6/1 云计算HCIP 周未班 2024/6/1 RHCA442 晚班 2024/6/17 周末班&#xff1a;周六-周日9:00-17:00晚 班&#xff1a;周一到周五19:00-21:30注&…

搜索的未来:OpenAI 的 GPT 如何彻底改变行业

搜索的未来&#xff1a;OpenAI 的 GPT 如何彻底改变行业 概述 搜索引擎格局正处于一场革命的风口浪尖&#xff0c;而 OpenAI 的 GPT 处于这场变革的最前沿。最近出现了一种被称为“im-good-gpt-2-chatbot”的神秘聊天机器人&#xff0c;以及基于 ChatGPT 的搜索引擎的传言&am…

android zygote进程启动流程

一&#xff0c;启动入口 app_main.cpp int main(int argc, char* const argv[]) {if (!LOG_NDEBUG) {String8 argv_String;for (int i 0; i < argc; i) {argv_String.append("\"");argv_String.append(argv[i]);argv_String.append("\" ")…

Python语言基础学习(上)

目录 一、常量和表达式 二、变量和类型 2.1 认识变量 2.2 定义变量 2.3 变量类型 1、整数 int 2、浮点数&#xff08;小数&#xff09;float 3、字符串 str 4、布尔类型 2.4 类型转换 三、注释 3.1 单行注释 3.2 文档注释&#xff08;或者多行注释&#xff09; …

[附源码]石器时代_恐龙宝贝内购版_三网H5手游_带GM工具

石器时代之恐龙宝贝内购版_三网H5经典怀旧Q萌全网通手游_Linux服务端源码_视频架设教程_GM多功能授权后台_CDK授权后台 本教程仅限学习使用&#xff0c;禁止商用&#xff0c;一切后果与本人无关&#xff0c;此声明具有法律效应&#xff01;&#xff01;&#xff01;&#xff0…

SpringBoot工作原理

优点&#xff1a;自动装配&#xff0c;起步依赖 起步依赖 原理就是maven的依赖传递 【A依赖B、B依赖C….&#xff0c;则我导入依赖A的时候&#xff0c;B&#xff0c;C都会被maven加载进来】 重点看看自动装配 概念&#xff1a; 当Spring容器启动后&#xff0c;一些配置类、…

攻略:ChatGPT3.5~4.0(中文版)国内无限制免费版(附网址)【2024年5月最新更新】

一、什么是ChatGPT&#xff1f; 1、ChatGPT的全名是Chat Generative Pre-trained Transformer&#xff0c;其中"chat"表示聊天。"GPT"则是由三部分组成&#xff1a;生成式&#xff08;generative&#xff09;意味着具有创造力&#xff1b;预训练&#xff0…

LeetCode 难题解析 —— 正则表达式匹配 (动态规划)

10. 正则表达式匹配 思路解析 这道题虽然看起来不难理解&#xff0c;但却存在多种可能&#xff0c;当然这种可能的数量是有限的&#xff0c;且其规律对于每一次判别都使用&#xff0c;所以自然而然就想到用 动态规划 的方法啦 接下来逐步分析可能的情况&#xff1a; &#x…

3---Linux编译器gcc/g++

一、程序的翻译过程&#xff1a;ESc->iso 1.1预处理&#xff1a;c->c 主要功能&#xff1a;宏替换、头文件的展开、条件编译、去注释&#xff1b;目的是让代码变得纯粹。条件编译&#xff0c;可以实现对代码的裁剪。比如对于不同用户&#xff0c;设置不同的宏常量&…

详解分布式锁

知识点&#xff1a; 单体锁存在的问题&#xff1a; 单体锁&#xff0c;即单体应用中的锁&#xff0c;通过加单体锁&#xff08;synchronized或RentranLock&#xff09;可以保证单个实例并发安全 单体锁是JVM层面的锁&#xff0c;只能保证单个实例上的并发访问安全 如果将单…

java JMH 学习

JMH 是什么&#xff1f; JMH&#xff08;Java Microbenchmark Harness&#xff09;是一款专用于代码微基准测试的工具集&#xff0c;其主要聚焦于方法层面的基准测试&#xff0c;精度可达纳秒级别。此工具由 Oracle 内部负责实现 JIT 的杰出人士编写&#xff0c;他们对 JIT 及…

鸿蒙内核源码分析(任务切换篇) | 看汇编如何切换任务

在鸿蒙的内核线程就是任务&#xff0c;系列篇中说的任务和线程当一个东西去理解. 一般二种场景下需要切换任务上下文: 在线程环境下&#xff0c;从当前线程切换到目标线程&#xff0c;这种方式也称为软切换&#xff0c;能由软件控制的自主式切换.哪些情况下会出现软切换呢? 运…

【AutoGPT】踩坑帖(follow李鱼皮)

本文写于2024年5月7日 参考视频&#xff1a;AutoGPT傻瓜式使用教程真实体验&#xff01; 对应文章&#xff1a;炸裂的AutoGPT&#xff0c;帮我做了个网站&#xff01; 平台&#xff1a;GitPod 云托管服务 原仓库已经改动很大&#xff0c;应使用的Repo为&#xff1a;Auto-GPT-ZH…

应用层协议之 DNS 协议

DNS 就是一个域名解析系统。域名就是网址&#xff0c;类似于 www.baidu.com。网络上的服务器想要访问它&#xff0c;就得需要它对应的 IP 地址&#xff0c;同时&#xff0c;每个域名对对应着一个 / N个 IP 地址&#xff08;即对应多台服务器&#xff09;。 因此&#xff0c;为了…

如何编译不同目录下的两个文件

1.直接编译 2.打包成动静态库进行链接

【bug记录】清除僵尸进程,释放GPU显存

目录 1. 为什么会出现这种情况&#xff1f;2. 解决方案方法一&#xff1a;使用 fuser 命令方法二&#xff1a; 3. 小贴士 在进行深度学习或其他需要GPU支持的任务时&#xff0c;我们有时会发现虽然没有可见的进程在执行&#xff0c;但GPU资源却意外地被占用。这种情况往往会阻碍…

如何确保UDP文件传输工具有最低稳定的传输速度?

在当前日新月异的数字时代背景下&#xff0c;文件传输工具已经成为我们日常生活与工作中不可或缺的一部分&#xff0c;尤其针对那些频繁涉及即时数据交互与多媒体流通的场景。 UDP协议&#xff0c;以其突出的高速传输与低延迟特性&#xff0c;脱颖而出成为众多用户的首选。不过…

这3种深拷贝实现,你都知道吗?

目录&#xff1a; 1、JSON.parse 2、structuredClone 3、cloneDeep

实习报告怎么写?笔灵AI实习体验报告模版分享:AI产品前端实习生

实习报告怎么写&#xff1f;笔灵AI实习体验报告模版可以帮你 点击即可使用&#xff1a;https://ibiling.cn/scene/inex?fromcsdnsx 下面分享AI产品前端实习生的实习报告 尊敬的导师和领导们&#xff1a;首先&#xff0c;我想对你们表达我的诚挚感谢&#xff0c;感谢你们给我…

C# WinForm —— 12 ListBox绑定数据

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