蓝桥杯C++:数据结构

1. vector 顺序表

💡 核心要点:vector 是动态变长数组,支持灵活的元素增删、大小调整,可实现一维 / 二维动态数组,通过成员函数操作。

1.1 基础使用

1.1.1 创建方式
  • 空数组:vector<类型> 名字;(如vector<int> a;
  • 固定长度 N(元素默认 0):vector<类型> 名字(N);(如vector<int> a(10);
  • 固定长度 N 且元素初始化为 valvector<类型> 名字(N, val);(如vector<int> a(100, 10);
  • 直接初始化元素:vector<类型> 名字{元素1, 元素2,...};(如vector<string> a{"a", "b"};
  • 二维动态数组(行数固定,列数可变):vector<类型> 名字[N];(如vector<int> a[5];
1.1.2 核心成员函数
  • size():返回实际元素个数;empty():返回布尔值,判断数组是否为空(均需加()调用)
  • begin()/end():返回迭代器(begin = 起始位置,end = 末尾元素下一位),支持范围 for 遍历:for(auto x : a)
  • push_back(x):末尾添加元素;pop_back():末尾删除元素
  • front():返回首元素;back():返回尾元素
  • resize(n):调整数组大小(n > 原大小补0 ,n < 原大小截断尾部)
  • clear():清空所有元素,数组变为空

1.2 专业补充 📚

  • vector 底层是连续内存,扩容时会重新分配内存并拷贝元素,可提前用reserve(n)预留空间优化性能;
  • 二维 vector 更灵活的写法:vector<vector<int>> a(n);(行数可动态调整,优于vector<int> a[n]);
  • 迭代器失效场景:扩容、非末尾插入 / 删除元素时,原有迭代器需重新获取。

1.3 适用场景 & 核心注意 ⚠️

  • 头文件:必须包含<vector>
  • 适用场景:需要动态调整大小的数组、不确定元素个数的存储(如刷题临时结果);
  • 避坑点:
    • 创建指定长度必须用(),而非[]vector<int> a(10)正确,vector<int> a[10]是创建 10 个空 vector);
    • 访问元素前需判断长度是否足够,避免越界;

2. 链表 list(数组模拟)

💡 核心要点:竞赛中常用数组模拟单链表(替代 STL 的 list),通过 h/e/ne 三个数组实现,支持高效的插入 / 删除操作,时间复杂度 O (1)。

2.1 基础使用

2.1.1 核心数组定义
  • h:哨兵头节点(head),初始值通常为 0;
  • e:存储元素值(element),e[id]表示第 id 个节点的元素;
  • ne:存储下一个节点的下标(next),ne[id]表示第 id 个节点的下一个节点下标;
  • id:节点计数,初始值通常为 0。
2.1.2 核心操作
  • 头插法添加元素

    cpp 复制代码
    id++;          // 新增节点编号
    e[id] = x;     // 赋值
    ne[id] = ne[h];// 新节点指向原头节点的下一个节点
    ne[h] = id;    // 头节点指向新节点
  • 任意位置 p 后插入元素:

    复制代码
    id++;
    e[id] = x;
    ne[id] = ne[p];
    ne[p] = id;
  • 遍历链表

    复制代码
    for(int i = ne[h]; i != 0; i = ne[i]) {
        // 操作e[i]
    }
  • 删除 p 后面的元素

    复制代码
    void erase(int p) { // p表示元素的位置
        if(ne[p]) {
            mp[e[ne[p]]] = 0; // 从mp中删除该元素(按需使用)
            ne[p] = ne[ne[p]]; // 跳过被删除节点
        }
    }

2.2 专业补充 📚

  • STL 的list 是双向链表,支持任意位置 O (1) 插入 / 删除,但遍历效率低于 vector(非连续内存),竞赛中极少使用
  • 哨兵节点(h)的作用:避免处理头节点为空的边界情况,简化代码。

2.3 适用场景 & 核心注意 ⚠️

  • 适用场景:需要频繁在任意位置插入 / 删除元素的场景(如链表模拟题、邻接表存储图);
  • 避坑点:
    • 节点编号 id 需从 1 开始(0 作为结束标记),避免与哨兵节点冲突;
    • 删除前需判断ne[p]是否为 0,避免访问空节点;
    • 数组大小需提前开足够(如 1e5),避免越界;
    • STL 的 list 时间复杂度高,竞赛优先用数组模拟

3. 栈 stack

💡 核心要点:后进先出 ,仅支持栈顶的插入(push)、删除(pop)和访问(top)操作。

3.1 基础使用

  • 头文件:<stack>
  • 创建方式:stack<类型> 名字;(如stack<string> st;);
  • 核心成员函数:
    • size()/empty():元素个数 / 判空;
    • push(x):将 x 压入栈顶;
    • pop():删除栈顶元素 ;
    • top():返回栈顶元素 。

3.2 专业补充 📚

  • stack 底层默认基于 deque 实现,也可指定底层容器(如stack<int, vector<int>> st;);
  • 型应用:括号匹配、表达式求值、深度优先搜索(DFS)。

3.3 适用场景 & 核心注意 ⚠️

  • 头文件:<stack>
  • 适用场景:需要 "后进先出" 逻辑的场景(如括号匹配、函数调用栈模拟);
  • 避坑点:
    • 使用top()前必须用empty()判断栈是否为空,避免程序崩溃;
    • pop()仅删除元素,不返回值(需先top()pop())。

4. 队列 queue

💡 核心要点: 先进先出 支持队尾插入(push)、队头删除(pop),可访问队头 / 队尾元素。

4.1 基础使用

  • 头文件:<queue>
  • 创建方式:queue<类型> 名字;(如queue<int> q;);
  • 核心成员函数:
    • size()/empty():元素个数 / 判空;
    • push(x):将 x 插入队尾;
    • pop():删除队头元素(无返回值);
    • front():返回队头元素;back():返回队尾元素。

4.2 适用场景 & 核心注意 ⚠️

  • 适用场景:需要 "先进先出" 逻辑的场景(如 BFS、消息队列);
  • 避坑点:使用front()/back()前需判断队列非空。

5. 优先级队列 priority_queue

💡 核心要点: 有序 ,默认降序(大根堆),插入自动排序,仅能访问 / 删除堆顶(优先级最高)元素。

5.1 基础使用

  • 头文件:<queue>(无单独头文件)

  • 创建方式:

    • 默认大根堆:priority_queue<类型> 名字;(如priority_queue<int> heap;);
    • 大根堆:priority_queue<int, vector<int>, less<int>> heap2;
    • 小根堆:priority_queue<int, vector<int>, greater<int>> heap3;
  • 核心成员函数:

    • size()/empty():元素个数 / 判空;
    • push(x):插入元素并自动排序;
    • pop():删除堆顶元素(无返回值);
    • top():返回堆顶元素;
  • 结构体排序(需重载<运算符)

    复制代码
    struct node {
        int b;
        bool operator < (const node& x) const {
            return b > x.b; // 小根堆(b小的优先级高)
        }
    };
    priority_queue<node> heap;

5.2 专业补充 📚

  • 底层是堆(完全二叉树),插入 / 删除时间复杂度 O (logn);
  • less<int>对应降序(大根堆),greater<int>对应升序(小根堆), 与sort的比较规则相反(sort 默认升序 = less<int>)。

5.3 适用场景 & 核心注意 ⚠️

  • 头文件:<queue>
  • 适用场景:动态获取最大值 / 最小值(如 TopK 问题、贪心算法);
  • 避坑点:
    • 结构体排序仅能重载<运算符(不能重载>);
    • 小根堆需指定三个模板参数(类型、底层容器、比较器)。

6. set 与 multiset

💡 核心要点: 有序无重复 ,++multiset 允许重复元素++,底层为红黑树,支持自动排序、查找、插入、删除,迭代器仅支持 ++/--

6.1 基础使用

  • 头文件:<set>
  • 创建方式:
    • set:set<类型> 名字;(如set<string> s;);
    • multiset:multiset<类型> 名字;(如multiset<int> ms;);
  • 核心成员函数:
    • size()/empty():元素个数 / 判空;
    • begin()/end():迭代器,支持范围 for 遍历(默认升序);
    • insert(x):插入元素(set 自动去重,multiset 允许重复);
    • erase(x):删除所有值为 x 的元素;++erase(迭代器):删除指定迭代器元素++;
    • find(x):查找 x,返回迭代器(不存在则返回 end ());
    • count(x):返回 x 的出现次数(set 中仅 0/1);
    • lower_bound(x):返回≥x 的最小元素迭代器
    • upper_bound(x):返回 > x 的最小元素迭代器

6.2 专业补充 📚

  • 迭代器使用需解引用
  • 底层是红黑树,操作时间复杂度 O (logn);
  • 迭代器仅支持双向移动(++/--),不支持随机访问(如it+1);
  • 范围 for 遍历是中序遍历,结果为升序。

6.3 适用场景 & 核心注意 ⚠️

  • 头文件:<set>
  • 适用场景:有序去重集合(set)、有序允许重复集合(multiset);
  • 避坑点:判断元素是否存在优先用count(x)(比find(x)便捷)。

7. map 与 multimap

💡 核心要点: 键值对有序集合(键唯一),multimap 允许重复键,底层为红黑树,可通过键快速访问值。

7.1 基础使用

  • 头文件:<map>
  • 创建方式:map<键类型, 值类型> 名字;(如map<string, int> mp;);
  • 核心特性:
    • 键唯一(multimap 允许重复键)
    • 方括号访问:****mp["张三"] = 90;(键不存在则自动插入,值默认初始化);
  • 核心成员函数:与 set 一致(insert/erase/find/count等,均针对键操作)。

7.2 专业补充 📚

  • 底层是红黑树,按键升序排列,操作时间复杂度 O (logn);
  • multimap 不支持方括号访问(键不唯一)

7.3 适用场景 & 核心注意 ⚠️

  • 头文件:<map>
  • 适用场景:键值对映射且键有序(如字典、统计频次);
  • 避坑点:避免直接用方括号判断键是否存在(会自动插入),应先用count()/find()

8. 哈希表(unordered_set/unordered_map)

💡 核心要点:unordered_set/unordered_map 是无序哈希表,底层为哈希表,操作平均 O (1),接口与 set/map 基本一致,不自动排序

8.1 基础使用

  • 头文件:<unordered_set>(unordered_set)、<unordered_map>(unordered_map);
  • 创建方式:
    • unordered_set:unordered_set<类型> 名字;(如unordered_set<int> us;);
    • unordered_map:unordered_map<键类型, 值类型> 名字;(如unordered_map<int, string> um;);
  • 核心成员函数:与 set/map 一致(++无lower_bound/upper_bound++)。

8.2 专业补充 📚

  • 底层是哈希表,平均操作 O (1),最坏 O (n)(哈希冲突);
  • 与 set/map 对比:速度更快但无序,set/map 有序但速度稍慢。

8.3 适用场景 & 核心注意 ⚠️

  • 头文件:<unordered_set>/<unordered_map>
  • 适用场景:不需要有序、追求快速查找 / 插入 / 删除(如高频判重、键值对查询);
  • 避坑点:
    • 无序,不能依赖遍历顺序;
    • 不支持lower_bound()/upper_bound()
    • 自定义结构体作为键需自定义哈希函数。

总结

  1. 语法规范 :创建指定长度的 vector 用()而非[],使用容器成员函数前需用empty()判空,priority_queue 的比较规则与 sort 相反;
  2. 核心特性:vector 是动态数组(连续内存),栈 / 队列是线性结构(LIFO/FIFO),set/map 是有序红黑树,unordered 系列是无序哈希表(更快);
  3. 竞赛技巧:链表优先用数组模拟(避免 STL list 的高复杂度),判重 / 查询优先用 unordered 系列(O (1)),有序场景用 set/map(O (logn))。
相关推荐
2401_873204652 小时前
C++代码重构实战
开发语言·c++·算法
wangchunting2 小时前
Jvm-垃圾回收算法
java·jvm·算法
北顾笙9802 小时前
day05-数据结构力扣
数据结构·leetcode·哈希算法
LCG元2 小时前
STM32嵌入式开发:基于PID算法的直流电机闭环调速控制
stm32·嵌入式硬件·算法
测试_AI_一辰2 小时前
Agent & RAG 测试工程笔记 14:RAG门控层拆解:什么时候该答?什么时候必须拒绝?
人工智能·算法·ai·自动化·ai编程
Σίσυφος19002 小时前
多频相位展开(Multi-frequency Phase Unwrapping)”可以替代格雷码?
算法
xiaolang_8616_wjl2 小时前
c++游戏_寻宝猎人_开源
开发语言·c++
暮冬-  Gentle°2 小时前
C++中的策略模式应用
开发语言·c++·算法
Yungoal2 小时前
1:const+volatile解决内存可见性问题,2:共享数据的访问导致竞争条件(Race Condition)
开发语言·c++·架构