核心按操作功能分类,每个功能下讲解不同数据结构的实现方式、用法、核心特点及跨结构区别,贴合算法刷题实际使用场景,所有内容均来自原文,无额外拓展。
一、插入操作
核心实现:push_back / push / insert / 数组模拟链表专属插入
1. vector:push_back(x)
- 尾部插入 ,示例:
vector<int> v; v.push_back(10); - 特点:底层连续内存,均摊时间复杂度 O (1),扩容时会重新分配内存。
2. stack(栈):push(x)
- 栈顶插入 x,示例:
stack<int> st; st.push(5); - 后进先出(LIFO)。
3. queue(队列):push(x)
- 队尾插入 x,示例:
queue<int> q; q.push(3); - 先进先出(FIFO)。
4. priority_queue(优先队列):push(x)
- 底层自动排序(默认大根堆),示例:
priority_queue<int> heap; heap.push(8); - 自动维护堆序,时间复杂度 O (logn),仅能从堆顶操作。
5. 数组模拟链表:头插 / 任意位置插(专属逻辑)
-
头插法 :id 从 1 开始,0 为结束标记,示例:
int h=0, e[1000], ne[1000], id=0; id++; e[id]=x; ne[id]=ne[h]; ne[h]=id; -
任意位置 p 后插 :
id++; e[id]=x; ne[id]=ne[p]; ne[p]=id; -
任意位置插入时间复杂度 O (1),竞赛首选(优于 STL list)。
6. set/unordered_set:insert(x)
- 插入单个元素 x,
- 示例:
set<int> s; s.insert(2);unordered_set<int> us; us.insert(2);
- 示例:
- set 自动升序 + 去重,unordered_set 无序 + 去重;底层分别为红黑树(O (logn))、哈希表(平均 O (1))。
7. map/unordered_map:insert({key, value})
- 插入键值对,示例:
map<int, string> m; m.insert({1, "abc"}); - map 按键升序 + 键唯一,unordered_map 无序 + 键唯一;
- map 的
[]也可实现插入(键不存在时自动创建),如m[2] = "def";。
插入操作 跨结构核心区别
- 插入位置限制:vector / 栈 / 队列仅支持固定位置插入(尾 / 栈顶 / 队尾),链表支持任意位置插入,红黑树 / 哈希表无显式位置(自动排序 / 哈希)。
- 插入特性:set/map/unordered 系列自动去重(map 按 key 去重),其余结构无自动去重;优先队列插入自动排序。
- 时间复杂度:链表 /vector/ 栈 / 队列插入为 O (1),红黑树(set/map)为 O (logn),哈希表(unordered 系列)平均 O (1)。
二、删除操作
核心实现:pop_back / pop / erase / 数组模拟链表专属删除
1. vector:pop_back()
- 尾部删除 ,无返回值,示例:
v.pop_back(); - O (1) 时间复杂度。
2. stack(栈):pop()
- 栈顶删除 ,无返回值,示例:
st.pop(); - 删栈顶前需用
empty()判空,避免崩溃。
3. queue(队列):pop()
- 队头删除 ,无返回值,示例:
q.pop(); - 删队头前需用
empty()判空。
4. priority_queue(优先队列):pop()
- 堆顶删除 ,无返回值,示例:
heap.pop(); - 删堆顶前需判空,删除后自动维护堆序。
5. 数组模拟链表:删除指定位置后元素(专属逻辑)
- 跳过被删除节点,示例:
void erase(int p) { if(ne[p]) ne[p] = ne[ne[p]]; } - O (1) 时间复杂度,删除前需判断
ne[p]!=0(避免空节点)。
6. set/unordered_set:erase(x) / erase(迭代器)
erase(x)删除所有值为 x 的元素,erase(迭代器)删除指定元素,示例:s.erase(2); s.erase(s.find(3));- set 为 O (logn),unordered_set 平均 O (1)。
7. map/unordered_map:erase(key) / erase(迭代器)
- 按键 删除,示例:
m.erase(1);m.erase(m.find(2)); - 与 set 一致,++仅操作对象为 key,而非元素值++。
删除操作 跨结构核心区别
- 删除位置限制:与插入位置强绑定(如栈删栈顶、队列删队头),仅链表 /set/map/unordered 系列支持指定元素 / 位置删除。
- 删除方式:vector / 栈 / 队列仅支持无参删除(固定位置),其余结构需指定元素 / 键 / 迭代器 / 位置。
- 返回值 :所有删除操作均无返回值(需先访问再删除)。
三、元素访问操作
核心实现:[] / front() / back() / top() / 迭代器解引用 / 数组直接访问
1. vector:v[idx] / front() / back()
v[idx]按下标访问(下标从 0 开始),front()取首元素,back()取尾元素,示例:v[0]; v.front();- 特点:随机访问 O (1),访问前需判断下标 < size (),避免越界。
2. 数组模拟链表:e[id]直接访问
- 通过节点 id 访问元素,示例:
e[1];(id 从 1 开始,0 为无效)
3. stack(栈):top()
- 仅访问栈顶元素 ,示例:
st.top(); - 访问前必须判空 。
4. queue(队列):front() / back()
- 用法 :
front()取队头,back()取队尾,示例:q.front(); q.back(); - 访问前必须判空,无法访问中间元素。
5. priority_queue(优先队列):top()
- 用法 :仅访问堆顶元素 (优先级最高),示例:
heap.top(); - 特点:访问前必须判空。
6. set/unordered_set:迭代器解引用*it
- 无
[],需通过 find / 遍历获取迭代器,再解引用,示例:auto it = s.find(2); cout << *it; - 特点 :迭代器仅支持 ++/--,不支持随机访问(如
it+1)。
7. map/unordered_map:m[key] / 迭代器it.first/it.second
m[key]按键访问值(键不存在则自动插入);迭代器中it.first为 key,it.second为 value,示例:m[1]; auto it = m.find(1); it->second;- 特点 :unordered_map 同 map;multimap 不支持
[](键不唯一)。
访问操作 跨结构核心区别
- 是否支持随机访问 :仅 vector 支持(下标
[]),其余所有结构均不支持。 - 访问范围限制:栈 / 队列 / 优先队列仅支持访问固定位置(栈顶 / 队头 / 堆顶等),无法访问中间元素。
- 专属访问方式:set/unordered_set 仅能通过迭代器解引用;map/unordered_map 支持按键访问和迭代器键值分离访问。
- 注意点 :
[]在 vector 中是下标访问 ,在 map 中是按键访问 ,并非同一概念;unordered 系列无lower_bound/upper_bound。
四、查找操作
核心实现:find() / count() / lower_bound() / upper_bound()(链表无内置查找,需手动遍历)
1. vector:无内置查找函数,需手动遍历 / 使用算法库find
- 连续内存,遍历查找 O (n),无专属查找接口。
2. 数组模拟链表:无内置查找,需手动遍历
for(int i=ne[h];i!=0;i=ne[i]) { if(e[i]==x) // 找到 }- 特点:遍历查找 O (n),无专属接口。
3. stack/queue/priority_queue:无任何查找接口
- 特点:仅支持固定位置的增删查,无法查找指定元素。
4. set/map:find(x) / count(x) / lower_bound(x) / upper_bound(x)
- 用法 :
find(x):set 查值、map 查键,返回迭代器(不存在则返回end());count(x):返回 x 的出现次数(set/map 中仅 0/1,即存在 / 不存在);lower_bound(x):返回≥x 的最小元素 / 键迭代器;upper_bound(x):返回 > x 的最小元素 / 键迭代器。
- 底层红黑树,所有查找操作 O (logn)。
5. unordered_set/unordered_map:find(x) / count(x)
- 与 set/map 一致(set 查值、map 查键);
find(x):set 查值、map 查键,返回迭代器(不存在则返回end());count(x):返回 x 的出现次数(set/map 中仅 0/1,即存在 / 不存在);lower_bound(x):返回≥x 的最小元素 / 键迭代器;upper_bound(x):返回 > x 的最小元素 / 键迭代器。
- 特点 :底层哈希表,平均 O (1);无
lower_bound/upper_bound(无序,无排序基础)。
查找操作 跨结构核心区别
- 是否有内置查找:stack/queue/priority_queue 无任何查找接口;vector / 链表需手动遍历;红黑树 / 哈希表系列有专属高效查找接口。
- 查找效率:哈希表系列(unordered)平均 O (1) > 红黑树系列(set/map)O (logn) > vector / 链表 O (n)。
- 查找拓展接口 :仅有序的 set/map 支持
lower_bound/upper_bound,无序的 unordered 系列无此接口。 - 查找对象 :set/unordered_set 查元素值 ,map/unordered_map 查键,二者不可混淆。
五、 size() / empty() / clear() / resize(n)
核心实现:size() / empty()(所有结构均支持,接口统一)
通用用法
size():返回实际元素个数,需加(),示例:v.size(); s.size(); st.size();empty():返回布尔值(true = 空,false = 非空),需加(),示例:q.empty(); heap.empty();
跨结构核心注意
- 接口完全统一 :所有数据结构的
size()/empty()用法、格式一致,无差异。 - 前置判断 :使用
top()/front()/back()/pop()等操作前,必须用empty()判空,避免访问空容器崩溃。 - vector 注意 :
v.size()返回无符号整数,避免与 int 比较出现越界(如i < v.size()而非i <= v.size()-1)。
六、清空 / 重置操作
核心实现:clear() / resize(n) / 手动重置(链表)
1. vector:clear() / resize(n)
clear():清空所有元素,size 变为 0,示例:v.clear();resize(n):调整大小,n > 原大小补 0,n < 原大小截断尾部,示例:v.resize(5);
2. set/unordered_set/map/unordered_map:clear()
- 清空所有元素,示例:
s.clear(); m.clear(); - 清空后 size 为 0,可重新插入元素。
3. stack/queue/priority_queue:无clear(),需手动清空
- 通过循环判空 + 删除实现,示例:
while(!st.empty()) st.pop();
4. 数组模拟链表:手动重置
- 重置头节点 h=0、节点计数 id=0,示例:
h=0; id=0; - 无内置清空接口,需手动恢复初始状态。
清空操作 跨结构核心区别
- 是否有内置
clear():vector/set/map/unordered 系列有,栈 / 队列 / 优先队列 / 数组模拟链表无。 - 无
clear()的处理方式 :栈 / 队列 / 优先队列用循环删 ,链表用手动重置初始值。 - vector 的 resize:不仅能清空,还能调整容器大小,是其专属拓展功能,其余结构无。
七、额外高频操作:遍历
核心实现:范围 for / 下标遍历 / 迭代器遍历 / 链表专属遍历
1. vector:下标遍历 / 范围 for / 迭代器
- 下标:
for(int i=0;i<v.size();i++) cout << v[i]; - 范围 for:
for(auto x : v) cout << x;
2. 数组模拟链表:专属遍历(按 ne 指针)
for(int i=ne[h];i!=0;i=ne[i]) cout << e[i];(0 为结束标记)
3. set/unordered_set/map/unordered_map:范围 for / 迭代器
- set:
for(auto x : s) cout << x;/for(auto it=s.begin();it!=s.end();it++) cout << *it; - map:
for(auto x : m) cout << x.first << x.second;(it.first=key,it.second=value)
4. stack/queue/priority_queue:无内置遍历方式,需手动导出后遍历
-
用法 :循环取顶 / 队头 + 删除,存入临时容器再遍历,示例:
stack<int> st, tmp; while(!st.empty()) { tmp.push(st.top()); st.pop(); } while(!tmp.empty()) { cout << tmp.top(); tmp.pop(); }
遍历操作 跨结构核心区别
- 遍历便捷性:vector(下标遍历)> 范围 for(set/map/unordered/vector)> 链表专属遍历 > 栈 / 队列手动遍历。
- 迭代器限制 :set/map/unordered 系列的迭代器仅支持 ++/--,不支持随机访问(如
it+1);vector 迭代器支持随机访问。 - 有序性 :set/map 遍历结果默认升序 ,unordered 系列遍历无序 ,其余结构遍历为插入顺序(vector / 链表 / 栈 / 队列)。
- 栈 / 队列:无原生遍历接口,需牺牲原容器(导出后删除),或复制容器后遍历。
