四、STL容器与数据结构

四、STL容器与数据结构(共17项)

1.C/C++中常用容器功能汇总

2.介绍一下vector优缺点

3.介绍一下list优缺点

4.介绍一下deque优缺点

5.介绍一下map&set优缺点

6.介绍一下mutable关键字的作用

7.map的底层原理是什么?

8.map和unordered_map了解吗?

9.hashmap和map的区别,底层数据结构算法是什么?

10.介绍一下红黑树?

11.介绍一下hash

12.介绍一下二叉树?

13.编程实现LRU

14.C/C++中数组和链表的优缺点?

15.容器选择的原则

16.什么是迭代器,有哪几种迭代器

17.vector的底层原理和扩容机制是什么?

结论先行

STL 容器可按序列式/关联式/无序关联式三类理解,选型核心看:

  • 随机访问多 → vector
  • 频繁插入删除 → list
  • 两端操作 → deque
  • 查找+有序 → map/set(红黑树);
  • 查找+无序 → unordered_map(哈希表);
  • 算法题常客 LRU → 哈希表 + 双向链表 🎯

逐条说明

1. 常用容器功能汇总
容器 底层 特点
vector 动态数组 随机访问快,尾部插入快
list 双向链表 插入删除快,无随机访问
deque 分段连续数组 头尾插入删除都快
stack/queue 适配器 基于 dequelist
set/map 红黑树 有序,O(log⁡n)O(logn)
unordered_set/map 哈希表 平均 O(1)O(1),无序
2. vector 优缺点

✅ 随机访问 O(1)O(1),尾部插入均摊 O(1)O(1),内存连续缓存友好

❌ 中间/头部插入慢,扩容有重新分配和拷贝开销

3. list 优缺点

✅ 任意位置插入删除 O(1)O(1)

❌ 无随机访问,内存不连续,缓存不友好

4. deque 优缺点

✅ 头尾插入删除 O(1)O(1),支持随机访问

❌ 中间插入慢,迭代器实现复杂

5. map & set 优缺点

✅ 自动排序,查找/插入/删除 O(log⁡n)O(logn)

❌ 比哈希表慢,需要自定义比较器

6. mutable 关键字

允许在 const 成员函数中修改该成员,常用于缓存、计数器、互斥锁:

复制代码
class A {
    mutable int count = 0;
public:
    void foo() const { ++count; }  // ✅ OK
};
7. map 的底层原理

通常基于红黑树实现,键值按比较器有序排列,保证 O(log⁡n)O(logn) 的查找、插入、删除。

8. map vs unordered_map
维度 map unordered_map
底层 红黑树 哈希表
有序性 有序 无序
查找 O(log⁡n)O(logn) 平均 O(1)O(1),最坏 O(n)O(n)
内存 较少 较多
9. hashmap vs map,底层数据结构
  • map:红黑树,有序,O(log⁡n)O(logn)
  • hashmapunordered_map):哈希表 + 拉链/开放寻址,平均 O(1)O(1)
10. 红黑树

自平衡二叉搜索树,五大性质保证高度近似 log⁡nlogn:

  1. 节点红或黑
  2. 根黑
  3. 叶子(NIL)黑
  4. 红节点的子节点黑
  5. 任意节点到叶子路径黑节点数相同

通过旋转 + 变色维持平衡。

11. 哈希(Hash)

通过哈希函数把键映射到数组下标,实现快速查找。

冲突解决方法:拉链法、开放寻址法、再哈希法等。

12. 二叉树

每个节点最多两个子节点的树结构。常见变体:

  • 二叉搜索树(BST)
  • 平衡二叉树(AVL)
  • 红黑树
  • 堆(完全二叉树)
13. 编程实现 LRU

核心:哈希表 + 双向链表,保证 O(1)O(1) 查找和删除:

复制代码
class LRUCache {
    int cap;
    list<pair<int,int>> lst;  // (key, value)
    unordered_map<int, list<pair<int,int>>::iterator> mp;
public:
    LRUCache(int capacity) : cap(capacity) {}
    int get(int key) {
        if (!mp.count(key)) return -1;
        lst.splice(lst.begin(), lst, mp[key]);  // 移到队头
        return mp[key]->second;
    }
    void put(int key, int val) {
        if (mp.count(key)) {
            mp[key]->second = val;
            lst.splice(lst.begin(), lst, mp[key]);
        } else {
            if (lst.size() == cap) {
                mp.erase(lst.back().first);
                lst.pop_back();
            }
            lst.emplace_front(key, val);
            mp[key] = lst.begin();
        }
    }
};
14. 数组 vs 链表
维度 数组 链表
访问 随机 O(1)O(1) 顺序 O(n)O(n)
插入删除 中间 O(n)O(n) O(1)O(1)
内存 连续,缓存友好 不连续
扩容 需要重新分配 动态增长
15. 容器选择原则
  • 需要索引/排序 → vector / deque
  • 频繁插入删除中间元素 → list
  • 键值查找且需有序 → map/set
  • 键值查找只需快 → unordered_map/set
  • 优先保证缓存友好 → 连续容器
16. 迭代器及种类

迭代器是访问容器元素的"泛型指针"。C++ 分 5 类:

迭代器 能力
输入迭代器 只读,单次遍历
输出迭代器 只写,单次遍历
前向迭代器 可多读,单向
双向迭代器 可双向移动(list
随机访问迭代器 +n-nvector
17. vector 底层原理和扩容机制

底层是一块连续动态数组

  • size():当前元素数
  • capacity():容量

扩容:当 size == capacity 时,重新申请更大内存(常见 1.5 倍或 2 倍),拷贝/移动元素,释放旧内存。

  • GCC libstdc++:2 倍
  • MSVC:1.5 倍

频繁扩容可先用 reserve 预分配,减少拷贝开销 ⚡


整体联系

这 17 题串起了 STL 容器选型 → 底层数据结构 → 算法复杂度 → 经典应用(LRU)

容器接口

底层数据结构

时间/空间复杂度

场景化选型

LRU等经典实现

理解底层(数组、链表、红黑树、哈希表),才能真正做到用对容器、写出高效代码 🚀

相关推荐
QX_hao1 小时前
【Go】--Cobra-cli的用法
开发语言·后端·golang
程与留1 小时前
07_QMainWindow 与应用程序框架——菜单栏、工具栏、状态栏
c++·qt
艾醒(AiXing-w)1 小时前
LangChain 1.0 入门(三):稳定性双核心——重试机制+速率限速器参数详解与实战
开发语言·langchain·php
总有刁民想爱朕ha2 小时前
Python PyQt5图片批量转MP4视频工具:本地离线免费无水印,完整代码
开发语言·python·qt
宸津-代码粉碎机2 小时前
FastUtil+AI多Agent实战:Java AI项目性能终极加速方案
java·服务器·开发语言·python·安全·php
_Narcissus_2 小时前
二分算法笔记及例题
数据结构·c++·笔记·算法·蓝桥杯·查找·二分算法
Python私教2 小时前
Python 3.15 来了:free-threading 稳定 ABI 能给高并发服务带来什么
开发语言·python
Logintern093 小时前
[Matlab] 遗传算法求解TSP入门
开发语言·matlab
万法若空4 小时前
CSP-J/S 排序算法完整专题训练题单
数据结构·算法·排序算法