- gf24153 的博客
《Mod笔谈:数据结构综合》
- @ 2026-7-15 17:07:28
这篇介绍一下数据结构
1.数组
这个可真的太普遍了,就是一个个数据组合在一起的数据结构,他们之间有一定的顺序,但大多数时候是不相关联的。
格式如下
数据类型 a[所装数据的数量];

这里就要注意了,数组是可以通过数据所在位置来进行索引的(就是通过位置找到他,并且非常快速,这就是数组的优势区间)
但是,用的时候要注意,数组的起始位置为0,就是第一个位置其实叫第个位置
2.字符串
用它之前也要写他的头文件
#include<string>
3.vector
我觉得他有点像Python里的列表,可以在中间插入数据,也可以在中间删除数据,还可以从末尾加入数据,可以随意索引数据,如果论实现各个功能所需的时间复杂度,vector的速度无疑是快过数组的(但他的第一个位置也叫第个)
那么他有什么缺点吗?
函数多啊!!!
vector<数据类型>v;#创建方式
v[数据位置];#索引方式
v.push_back(数据);#在末尾放入数据
v.at(数据位置)= ;#修改该位置数据
v.resize(要装数据的数量);#提前留几个位置,方便索引(vector没法初始化,所以他的初始大小为$0$)
v.insert(位置,数据);#在该位置前插入数据
v.pop_back();#删除末尾数据
v.erase(位置);#删除该位置的数据
······
记不住就没必要记了,反正你用数组也够了
6.栈
tips:记得加头文件
#include<stack>
栈,大概长这样

他可以直接从口放进去,但是他却只能从口出,所以他的数据是先进的后出
stack <数据类型> s;#创建方式
s.push();#放入代码
s.pop();#删除代码
s.top();#索引栈顶
s.empty()#看看他是不是空的
s.size()#纯检查长度来了
相信你也看出来了,他只能索引一个
而且他每次更改也只能一个个改
也就是说……,他删除一个数字,最坏要把所有其他数字全删了,还得把他们都加回来……
我说白了,队列起码还有双端的和会自动排序的,这个栈完全就是

7.队列
用它时也要加一个
#include<queue>
而他长这样

他的代码为
queue <数据类型> q;#创建方式
q.push();#放入代码
q.pop();#删除代码
q.front();#索引队头
q.empty()#看看他是不是空的
q.size()#检查长度来了
他和栈有点相同的一点……
中间的永远无法索引
但是他是两端的,也就是先进去的先出来!
而且他还有他的变种,感兴趣的自行观看
双端队列
需要特殊的头文件
#include<deque>
双端队列就是把栈和队列融合在一起,可以两头进两头出
如图:

这样我们就可以更加便捷的维护了
代码如下
- 构造与初始化
deque dq;:默认构造空队列 deque dq(5, 10);:5个值为10的元素 deque dq = {1, 2, 3};:列表初始化
- 增删元素(两端高效 O(1))
| 操作 | 说明 |
|---|---|
| push_back(val) | 尾部插入 |
| push_front(val) | 头部插入 (Vector不支持) |
| pop_back() | 删除尾部元素 |
| pop_front() | 删除头部元素 |
| insert(pos, val) | 指定位置插入 (效率较低) |
| erase(pos) | 删除指定位置元素 |
- 访问与查询 front() / back():获取首/尾元素引用 dq[i] / dq.at(i):随机访问(at带越界检查) size() / empty():大小与判空
单调队列
1. 核心定义
单调队列是一种特殊的双端队列,队列内的元素严格保持单调递增或单调递减的顺序,入队时会自动移除破坏单调性的无效元素,整体操作时间复杂度为O(n)其实还要你自己维护。
2. 核心特性
- 依托双端队列实现,支持两端高效增删
- 队头元素始终是当前维护区间内的最大值/最小值
- 所有元素仅入队、出队各一次,无冗余重复遍历
3. 标准操作流程
- 队尾维护:新元素入队时,从队尾依次弹出所有破坏单调性的元素,保证队列有序
- 队头清理:从队头弹出超出当前有效区间的过期元素
- 获取极值:此时队头元素即为当前区间的目标极值
4. 经典应用场景
场景1:滑动窗口最大值
在长度为k的滑动窗口移动过程中,O(n)复杂度输出所有窗口的最大值,是单调队列最典型的入门题。
场景2:前缀和优化子数组问题
比如题「和至少为K的最短子数组」,通过维护单调递增的前缀和队列,快速筛选出满足条件的最短子数组。
5. C++ 核心实现模板
#include <deque>
#include <vector>
using namespace std;
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq; // 存储数组下标,方便判断窗口边界
vector<int> res;
for(int i = 0; i < nums.size(); i++){
// 1. 队尾维护:弹出比当前元素小的元素,保持队列单调递减
while(!dq.empty() && nums[i] >= nums[dq.back()])
dq.pop_back();
dq.push_back(i);
// 2. 队头清理:移除超出窗口范围的过期下标
if(dq.front() == i - k)
dq.pop_front();
// 3. 窗口形成后,记录队头的最大值
if(i >= k - 1)
res.push_back(nums[dq.front()]);
}
return res;
}
优先队列
1. 核心定义
优先队列说白了就是会排序的队列,他会把数据按照优先级大小来排序,每次出去的都是里面优先级最大的,换句话说,如果是char类型,'A'会比'a'出去的晚(因为char类型的排序是依靠ASCALL码的大小),通常基于二叉堆实现反正你又不知道二叉堆。
它不需要额外加头文件,因为他已经在queue里了
2. 核心特性
- 英文名叫priority_queue,默认是大顶堆
- 核心操作时间复杂度稳定为O(log n),取队首极值仅需O(1)
- 支持自定义比较规则,灵活切换大顶堆/小顶堆模式
3. 基础操作速查
| 操作 | 说明 | 时间复杂度 |
|---|---|---|
push(val) |
插入元素并维护堆结构 | O(log n) |
pop() |
移除优先级最高的队首元素 | |
top() |
获取队首极值元素,不删除 | O(1) |
empty() / size() |
判空/获取队列元素总数 | |
| priority_queue<> q; | 创建方式 | 这你也想知道? |
总而言之,队列大概就是
