☰
C++ 常用数据结构速查:vector、stack、queue、list、树、图、哈希表等声明与核心操作
2026/10/15 19:35:55 网站建设 项目流程

万能头文件

#include <bits/stdc++.h> using namespace std;

bits/stdc++.h 包含了绝大多数标准库头文件,在算法竞赛和面试手撕代码时能显著节省书写时间。

注意:这是 GCC 编译器特有的非标准头文件,在 MSVC 或某些严格环境下可能无法使用,但在绝大多数在线笔试平台(牛客、LeetCode C++ 环境通常支持 GCC)中可正常工作。

一、动态数组 vector

声明:

vector<int> v; // 空数组 vector<int> v(10); // 10 个 0 vector<int> v(10, 5); // 10 个 5 vector<vector<int>> matrix(5, vector<int>(5, 0)); // 5x5 二维数组 vector<int> v = {1, 2, 3}; // 列表初始化

常用操作:

操作

代码

复杂度

尾部添加

v.push_back(x)

均摊 O(1)

尾部删除

v.pop_back()

O(1)

访问元素

v[i] 或 v.at(i)

O(1)

首尾迭代器

v.begin(), v.end()

O(1)

大小/空判断

v.size(), v.empty()

O(1)

指定位置插入

v.insert(v.begin()+i, x)

O(n)

指定位置删除

v.erase(v.begin()+i)

O(n)

调整大小

v.resize(n)

O(n)

排序

sort(v.begin(), v.end())

O(n log n)

二分查找(有序)

binary_search(v.begin(), v.end(), x)

O(log n)

常用技巧:

// 去重(需先排序) sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); // 二维数组遍历 for (auto& row : matrix) { for (int x : row) cout << x << " "; }

二、栈 stack

声明:

stack<int> s;

常用操作:

操作

代码

入栈

s.push(x)

出栈

s.pop()(无返回值)

取栈顶

s.top()

判空

s.empty()

大小

s.size()

栈适用于括号匹配、逆波兰表达式求值、单调栈等场景。底层默认使用 deque,但是相对来说算是细节,一般不需要关心 。

三、队列 queue

声明:

queue<int> q;

常用操作:

操作

代码

入队

q.push(x)

出队

q.pop()(无返回值)

取队首

q.front()

取队尾

q.back()

判空/大小

q.empty(), q.size()

BFS 的标配容器。如果需要双端操作,使用 deque:

deque<int> dq; dq.push_back(x); // 尾插 dq.push_front(x); // 头插 O(1) dq.pop_back(); dq.pop_front();

四、优先队列 priority_queue

声明:

priority_queue<int> pq; // 大顶堆(默认) priority_queue<int, vector<int>, greater<int>> min_pq; // 小顶堆

常用操作:

操作

代码

插入

pq.push(x)

删除堆顶

pq.pop()

取堆顶

pq.top()

判空/大小

pq.empty(), pq.size()

自定义类型:

struct Node { int dist; int id; }; struct cmp { bool operator()(Node& a, Node& b) { return a.dist > b.dist; // 距离小的优先级高(小顶堆) } }; priority_queue<Node, vector<Node>, cmp> pq;

适用于 Dijkstra、Top K 问题、任务调度等 。

五、链表 list

声明:

list<int> lst;

常用操作:

操作

代码

头/尾插入

lst.push_front(x), lst.push_back(x)

头/尾删除

lst.pop_front(), lst.pop_back()

指定位置插入

lst.insert(it, x)

删除元素

lst.erase(it)

排序

lst.sort()

判空/大小

lst.empty(), lst.size()

list 是双向链表,不支持随机访问[]。插入删除 O(1)(已知迭代器位置),但查找 O(n) 。

手撕链表通常需要手写节点结构,因为面试官考察的是指针操作:

struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} };

六、树(set / map:平衡二叉搜索树)

STL 没有直接提供“树”容器,但 set 和 map 底层是红黑树(平衡 BST),提供 O(log n) 的有序操作。

set(有序集合,去重)

声明:

set<int> s;

常用操作:

s.insert(x); // 插入 O(log n) s.erase(x); // 删除 s.find(x); // 查找,返回迭代器 s.count(x); // 存在返回 1 s.lower_bound(x); // >= x 的第一个元素 s.upper_bound(x); // > x 的第一个元素

map(有序键值对)

声明:

map<string, int> mp;

常用操作:

mp["key"] = 1; // 插入/修改 mp.insert({"key", 1}); mp.erase("key"); mp.find("key"); // 返回迭代器 mp.count("key"); // 判断存在 for (auto& [k, v] : mp) // C++17 结构化绑定遍历 cout << k << ": " << v;

手写二叉树节点

struct TreeNode { int val; TreeNode *left, *right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} };

七、哈希表 unordered_map / unordered_set

声明:

unordered_map<int, int> hashmap; // 键值对 unordered_set<int> hashset; // 集合

常用操作(与 map/set 类似,但无序):

操作

代码

平均复杂度

插入/修改

mp[key] = val

O(1)

查找

mp.find(key)

O(1)

存在判断

mp.count(key)

O(1)

删除

mp.erase(key)

O(1)

关键区别:

unordered_map 平均 O(1),但最坏 O(n)(哈希冲突),且无序

map 稳定 O(log n),有序,可用 lower_bound

面试中涉及“查找/计数/去重”且不要求顺序时,优先使用 unordered_map 或 unordered_set 。

八、图(邻接表表示)

C++ STL 没有内置图容器,通常用 vector 模拟邻接表:

// 邻接表:g[u] 存储 u 的所有邻居 vector<vector<int>> g(n + 1); // 添加有向边 u -> v g[u].push_back(v); // 添加无向边 g[u].push_back(v); g[v].push_back(u); // 带权图:pair<邻点, 权重> vector<vector<pair<int, int>>> wg(n + 1); wg[u].push_back({v, w});

BFS 遍历模板:

queue<int> q; vector<bool> visited(n + 1, false); q.push(start); visited[start] = true; while (!q.empty()) { int u = q.front(); q.pop(); for (int v : g[u]) { if (!visited[v]) { visited[v] = true; q.push(v); } } }

DFS 递归模板:

void dfs(int u, vector<vector<int>>& g, vector<bool>& visited) { visited[u] = true; for (int v : g[u]) { if (!visited[v]) dfs(v, g, visited); } }

九、C++17 结构化绑定(强烈推荐)

在遍历 map 或 vector<pair> 时,结构化绑定可以大幅简化代码:

// 以前 for (auto& it : mp) { cout << it.first << " " << it.second; } // C++17 for (auto& [key, value] : mp) { cout << key << " " << value; }

配合 auto&& 使用可以避免不必要的拷贝。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询