C++STL细节,底层实现,面试题04

news/2024/9/23 6:23:23/

文章目录

  • 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.ppmy.cn/news/1459314.html

相关文章

JAVA文件的简单操作

文件IO&#xff08;Input和Output&#xff09; 文件的输入和输出是人为规定的&#xff0c;那么什么是输入&#xff1f;什么是输出捏&#xff1f;在这里统一已CPU为基准 例如&#xff1a;将文件由内存写入硬盘就是输出&#xff0c;有硬盘写入内存就是输入。可以总结为&#xff…

泛娱乐出海新趋势

在全球化和数字化浪潮的推动下&#xff0c;泛娱乐领域正在经历快速变革&#xff0c;中国应用开发者纷纷走向全球市场&#xff0c;并且在国际舞台上大放异彩&#xff0c;据Sensor Towers数据显示&#xff0c;2023年10月&#xff0c;中国移动发行商的收入占全球应用收入的38.7%&a…

Adobe Acrobat Pro DC 2022一款高效强大的PDF阅读编辑专业软件(240506)

01 软件介绍 Adobe Acrobat Pro DC 2022&#xff0c;作为一款专业的PDF处理工具&#xff0c;它集成了强大的制作功能&#xff0c;能够与Adobe Photoshop的高级图像编辑能力无缝衔接&#xff0c;进而将各类纸质文档高效转换成可编辑的电子格式&#xff0c;以便于文件的传输和签…

设计模式之服务定位器模式

想象一下&#xff0c;你的Java应用是一座庞大的迷宫&#xff0c;里面藏着无数宝贵的服务宝藏&#xff0c;而你正需要一张精确的藏宝图来指引方向&#xff0c;迅速找到并利用这些宝藏。服务定位器模式&#xff0c;正是这样一张神奇的地图&#xff0c;它帮你动态定位并获取应用中…

Linux 操作系统线程1

目录 一、线程 1.1线程的基本概念 1.2 线程相关的API函数 1.2.1 线程的创建 1.2.2 线程退出 1.2.3 线程等待函数 1.2.4 获取线程ID 1.2.5 线程取消 1.2.6 线程的清理函数 一、线程 1.1线程的基本概念 线程是属于进程&#xff1b;一个进程可以有多个线程&#xff…

描述Nacos中服务发现的流程。

Nacos中服务发现的流程解析 在微服务的架构体系中&#xff0c;服务发现是一个至关重要的组成部分。它解决了服务提供者和消费者之间如何动态发现对方地址的问题&#xff0c;使得微服务之间的调用更加灵活和高效。在众多服务发现组件中&#xff0c;Nacos以其易用性、高性能和丰…

C++关联容器2——map,multimap,set,multiset基本操作

目录 关联容器操作 关联容器迭代器 set 的迭代器是const的 遍历关联容器 关联容器和算法 添加元素 向map添加元素 检测insert的返回值 向multiset或 multimap添加元素 std::multiset 例子 std::multimap 例子 删除元素 std::set 和 std::multiset 示例 std::map 和…

『python办公自动化』Excel:标红低于100的数据

theme: smartblue &#x1f440; 点赞 关注 收藏 学会了 &#x1f4da; 专栏&#xff1a;写给产品经理的办公自动化教程 本文简介 作为产品经理&#xff0c;收集和分析数据是必备技能。我们的产品可能会设置埋点监听用户行为、记录页面和某些功能的使用情况。你问研发同事拿…