四、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等经典实现

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

相关推荐
2601_966949655 小时前
为什么量化策略需要大量历史股票数据?从回测可信度理解数据规模
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
niucloud-admin5 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
anew___5 小时前
蜂鸣器播放音乐——让 Arduino 唱出旋律
c++·stm32·单片机·嵌入式硬件·c
吞下星星的少年·-·5 小时前
The 2026 ICPC Asia East Continent Online Contest (II)(构造)
数据结构·算法
滕州市燕猫虎计算机科技工作室个体工商户5 小时前
Java锁
java·开发语言
多加点辣也没关系5 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
菜鸟~noob2336 小时前
【电子战】 第09篇:阵列信号处理——波束形成、MVDR、MUSIC【含matlab代码】
开发语言·matlab·信号处理
ocean21036 小时前
2025-2026年Python面试高频知识点洞察
开发语言·python·面试·python八股文
零依赖极客6 小时前
Day 6·1 ARMv8.2 dotprod——vdotq_s32 一条指令做 4 个点积
c语言·开发语言·人工智能·矩阵·arm·vllm
stolentime6 小时前
洛谷P10515 转圈题解
c++·算法·数学建模·贪心算法