144.145.194.二叉树的前/中/后递归遍历
- 递归三要素(核心方法论):
- 参数/返回值:确定递归需要的参数(如当前节点、结果数组),明确返回类型(通常void);
- 终止条件:遇到空节点
cur == NULL时返回,避免栈溢出; - 单层逻辑:按遍历顺序(中左右/左中右/左右中)处理当前节点+递归子节点。
- 遍历核心差异:仅在于“处理当前节点(存值)”的时机,递归逻辑完全复用;
- 复杂度:时间O(n)(遍历所有节点),空间O(n)(递归栈深度,最坏为链表结构)。
C++代码(整合前/中/后序)
// 二叉树节点定义(LeetCode默认)
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
private:
// 前序遍历:中左右
void preOrder(TreeNode* cur, vector<int>& res) {
if (!cur) return;
res.push_back(cur->val); // 中
preOrder(cur->left, res); // 左
preOrder(cur->right, res); // 右
}
// 中序遍历:左中右
void inOrder(TreeNode* cur, vector<int>& res) {
if (!cur) return;
inOrder(cur->left, res); // 左
res.push_back(cur->val); // 中
inOrder(cur->right, res); // 右
}
// 后序遍历:左右中
void postOrder(TreeNode* cur, vector<int>& res) {
if (!cur) return;
postOrder(cur->left, res); // 左
postOrder(cur->right, res); // 右
res.push_back(cur->val); // 中
}
public:
// 前序遍历入口
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
preOrder(root, res);
return res;
}
// 中序遍历入口
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
inOrder(root, res);
return res;
}
// 后序遍历入口
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
postOrder(root, res);
return res;
}
};
关键点回顾
- 递归核心:终止条件(空节点返回)是基础,单层逻辑仅调整“存值时机”;
- 复用性:前/中/后序的递归框架完全一致,仅改变
res.push_back(cur->val)的位置; - 传参技巧:结果数组
res需传引用(&),避免每次递归拷贝,提升效率。
144.145.194.二叉树的前/中/后迭代遍历
- 核心思路:用栈模拟递归调用栈,前序/后序可通过“中左右”基础逻辑调整实现,中序因“访问/处理顺序不一致”需配合指针遍历;
- 遍历规则:
- 前序:中左右 → 根入栈,弹栈处理根,先压右孩子再压左孩子(出栈为左→右);
- 中序:左中右 → 指针遍历到左底入栈,弹栈处理中,再遍历右孩子;
- 后序:左右中 → 复用前序逻辑(中右左),最后反转结果数组;
- 复杂度:时间O(n)(遍历所有节点),空间O(n)(栈存储节点)。
C++代码(前序→中序→后序)
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
// 1. 前序遍历(中左右)
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (!root) return res;
st.push(root);
while (!st.empty()) {
TreeNode* node = st.top(); st.pop();
res.push_back(node->val); // 中
if (node->right) st.push(node->right); // 右(先压后出)
if (node->left) st.push(node->left); // 左(后压先出)
}
return res;
}
// 2. 中序遍历(左中右)
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
TreeNode* cur = root;
while (cur || !st.empty()) {
if (cur) { // 指针遍历到左底
st.push(cur);
cur = cur->left; // 左
} else { // 弹栈处理中,再遍历右
cur = st.top(); st.pop();
res.push_back(cur->val); // 中
cur = cur->right; // 右
}
}
return res;
}
// 3. 后序遍历(左右中)
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if (!root) return res;
st.push(root);
while (!st.empty()) {
TreeNode* node = st.top(); st.pop();
res.push_back(node->val); // 中
if (node->left) st.push(node->left); // 左(先压后出)
if (node->right) st.push(node->right); // 右(后压先出)
}
reverse(res.begin(), res.end()); // 中右左 → 左右中
return res;
}
};
关键点回顾
- 前序核心:根先处理,栈“先右后左”入栈,保证出栈是“左→右”;
- 中序核心:指针负责“访问”(遍历到左底),栈负责“处理”(弹栈存值),分离访问与处理逻辑;
- 后序核心:复用前序逻辑得到“中右左”,反转数组即得“左右中”,无需单独设计复杂逻辑。
102.107.199.637.429.515.116.117.104.111二叉树迭代/递归层序遍历
- 核心思路:
- 迭代法(BFS):用队列实现,每次处理当前层所有节点(通过
que.size()固定层大小),按层收集结果; - 递归法(DFS):用
depth标记当前层数,按层将节点值存入结果数组;
- 迭代法(BFS):用队列实现,每次处理当前层所有节点(通过
- 关键细节:迭代法中必须用固定size遍历当前层(避免队列动态变化导致遍历不全);
- 复杂度:时间O(n)(遍历所有节点),空间O(n)(队列/递归栈存储节点)。
一、迭代法(层序遍历核心模板)
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
queue<TreeNode*> que;
if (root) que.push(root); // 根节点非空则入队
while (!que.empty()) {
int levelSize = que.size(); // 固定当前层节点数(关键,避免队列动态变化)
vector<int> levelRes; // 存储当前层的节点值
// 遍历当前层所有节点
for (int i = 0; i < levelSize; i++) {
TreeNode* node = que.front(); que.pop();
levelRes.push_back(node->val);
// 子节点非空则入队(为下一层遍历做准备)
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
res.push_back(levelRes); // 当前层结果加入最终结果
}
return res;
}
};
二、递归法
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
private:
// 递归辅助函数:按深度(层数)存储节点值
void traversal(TreeNode* cur, vector<vector<int>>& res, int depth) {
if (!cur) return; // 空节点直接返回
// 若当前深度未创建数组,新增一层
if (res.size() == depth) res.emplace_back();
// 将当前节点值存入对应深度的数组
res[depth].push_back(cur->val);
// 递归遍历左右子树,深度+1
traversal(cur->left, res, depth + 1);
traversal(cur->right, res, depth + 1);
}
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> res;
traversal(root, res, 0); // 从根节点、深度0开始递归
return res;
}
};
核心总结
- 迭代法:
- 核心是
queue+固定levelSize,确保每层节点被完整遍历; - 是层序遍历的“标准模板”,适配所有层序相关题目(如右视图、层平均值)。
- 核心是
- 递归法:
- 核心是
depth标记层数,通过res.size() == depth新增层数组; - 本质是DFS的变形,通过深度映射层数,逻辑更抽象但代码简洁。
- 核心是
两份代码完全独立,可直接复制使用,符合你“分开写”的要求,再次抱歉之前的整合错误!
关键点回顾
- 迭代法核心:
levelSize = que.size()固定当前层节点数,确保内层循环只处理当前层,避免队列动态添加子节点导致遍历越界; - 递归法核心:用
depth标记层数,res.size() == depth时新增层数组,保证节点值存入对应层; - 模板复用性:此迭代法代码可直接适配“层序遍历II、右视图、层平均值”等题目,仅需修改“层结果的处理逻辑”(如反转、取最后一个元素、求平均)。
&spm=1001.2101.3001.5002&articleId=158179511&d=1&t=3&u=42ce97e98cc140409694b879c12f9826)
290

被折叠的 条评论
为什么被折叠?



