STL 入门 + 三道高频面试题(二叉树层序 / 重建二叉树 / 两栈实现队列)
不懂 STL,不要说你会 C++。
本文整理了 STL 的核心概念、重要版本、六大组件,并结合三道经典面试题(JZ78、JZ7、JZ9)给出完整代码与解析,最后附带一份常见 C++ 面试问答。
一、STL 简介
1. 什么是 STL
STL(Standard Template Library,标准模板库) 是 C++ 标准库的核心组成部分。
它不仅仅是一个可复用的组件库,更是一个包罗数据结构与算法的软件框架。
2. STL 的发展版本(了解即可,但面试可能被问)
| 版本 | 特点 |
|---|---|
| HP 版本 | 始祖,开源 |
| P.J. 版本 | VC++ 使用,不可修改,可读性差 |
| RW 版本 | C++Builder 使用 |
| SGI 版本 | Linux GCC 使用,可读性好,推荐学习参考 |
我们平时读 STL 源码,主要参考 SGI 版本。
3. STL 六大组件
- 容器(vector、list、map...)
- 算法(sort、find...)
- 迭代器(容器与算法的桥梁)
- 仿函数(函数对象)
- 适配器(stack、queue...)
- 空间配置器(内存管理)
4. 学习 STL 的三个境界
- 第一层:能用
- 第二层:明理(原理、实现)
- 第三层:能扩展
参考:《The C++ Standard Library》
二、面试题 1:二叉树按层打印(JZ78)
https://www.nowcoder.com/practice/445c44d982d04483b04a54f298796288?tpId=13
题目描述
从上到下按层打印二叉树,同一层从左到右,每一层输出一行。
思路
- 使用 BFS + 队列
- 每次处理一整层(根据队列当前长度)
代码实现(C++)
cpp
class Solution {
public:
vector<vector<int>> Print(TreeNode* pRoot) {
vector<vector<int>> res;
if (!pRoot) return res;
queue<TreeNode*> q;
q.push(pRoot);
while (!q.empty()) {
int size = q.size();
vector<int> level;
for (int i = 0; i < size; ++i) {
TreeNode* node = q.front(); q.pop();
level.push_back(node->val);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
res.push_back(level);
}
return res;
}
};
复杂度
- 时间:O(n)
- 空间:O(n)
三、面试题 2:重建二叉树(JZ7)
https://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=13
题目描述
根据前序遍历 + 中序遍历(无重复值)重建二叉树。
思路(递归)
- 前序第一个 = 根节点
- 中序中根节点左边 = 左子树,右边 = 右子树
- 递归构建左右子树
代码实现(C++)
cpp
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
if (pre.empty()) return nullptr;
TreeNode* root = new TreeNode(pre[0]);
int pos = 0;
while (vin[pos] != pre[0]) ++pos;
vector<int> leftPre(pre.begin() + 1, pre.begin() + 1 + pos);
vector<int> leftVin(vin.begin(), vin.begin() + pos);
vector<int> rightPre(pre.begin() + 1 + pos, pre.end());
vector<int> rightVin(vin.begin() + pos + 1, vin.end());
root->left = reConstructBinaryTree(leftPre, leftVin);
root->right = reConstructBinaryTree(rightPre, rightVin);
return root;
}
};
复杂度
- 时间:O(n)
- 空间:O(n)
四、面试题 3:用两个栈实现队列(JZ9)
https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6?tpId=13
题目描述
用两个栈实现队列的 push 和 pop 操作,保证 pop 时队列非空。
思路(经典"倒腾"法)
- push:直接压入 stack1
- pop :
- 若 stack2 不为空,直接弹出 stack2
- 否则将 stack1 全部倒入 stack2,再弹出 stack2
代码实现(C++)
cpp
class Solution {
public:
void push(int node) {
stack1.push(node);
}
int pop() {
if (stack2.empty()) {
while (!stack1.empty()) {
stack2.push(stack1.top());
stack1.pop();
}
}
int res = stack2.top();
stack2.pop();
return res;
}
private:
stack<int> stack1;
stack<int> stack2;
};
复杂度
- 每个元素最多入栈 2 次、出栈 2 次 → 摊还 O(1)
五、C++ / STL 面试高频问答
1. 空间配置器和智能指针的联系?
- 都涉及内存管理,但层次不同:
- 空间配置器:管理原始内存
- 智能指针:管理对象生命周期
2. auto_ptr 为什么被 C++11 移除?
- 拷贝语义破坏(转移所有权),容易误用
- 替代:
unique_ptr/shared_ptr
3. nullptr 与 NULL 的区别?
NULL是 0nullptr是std::nullptr_t类型,更安全
4. vector 与 list 的区别
| 对比 | vector | list |
|---|---|---|
| 底层结构 | 连续数组 | 双向链表 |
| 随机访问 | O(1) | O(n) |
| 插入/删除 | 尾部快,中间慢 | 任意位置快 |
| 迭代器失效 | 易失效 | 不易失效 |
5. vector 扩容机制
- 通常 1.5 或 2 倍扩容
- 导致迭代器、引用失效
6. map 底层实现
- 红黑树,有序
unordered_map是哈希表,无序,平均 O(1)
7. 链表迭代器失效
- 删除当前节点 → 该迭代器失效
- 插入不影响已有迭代器
六、总结
- STL 是 C++ 开发者的必备技能
- 学习路径:会用 → 明理 → 扩展
- 面试中常结合 二叉树、栈、队列、容器底层原理 一起考察
如果你正在准备 C++ 开发岗,建议把这三道题 手写 3 遍以上,并且能把 STL 容器底层讲清楚。
如果有帮助,欢迎点赞、收藏、转发~