代码随想录:二叉树篇(上)

144.145.194.二叉树的前/中/后递归遍历

  1. 递归三要素(核心方法论)
    • 参数/返回值:确定递归需要的参数(如当前节点、结果数组),明确返回类型(通常void);
    • 终止条件:遇到空节点cur == NULL时返回,避免栈溢出;
    • 单层逻辑:按遍历顺序(中左右/左中右/左右中)处理当前节点+递归子节点。
  2. 遍历核心差异:仅在于“处理当前节点(存值)”的时机,递归逻辑完全复用;
  3. 复杂度:时间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;
    }
};

关键点回顾

  1. 递归核心:终止条件(空节点返回)是基础,单层逻辑仅调整“存值时机”;
  2. 复用性:前/中/后序的递归框架完全一致,仅改变res.push_back(cur->val)的位置;
  3. 传参技巧:结果数组res需传引用(&),避免每次递归拷贝,提升效率。

144.145.194.二叉树的前/中/后迭代遍历

  1. 核心思路:用栈模拟递归调用栈,前序/后序可通过“中左右”基础逻辑调整实现,中序因“访问/处理顺序不一致”需配合指针遍历;
  2. 遍历规则
    • 前序:中左右 → 根入栈,弹栈处理根,先压右孩子再压左孩子(出栈为左→右);
    • 中序:左中右 → 指针遍历到左底入栈,弹栈处理中,再遍历右孩子;
    • 后序:左右中 → 复用前序逻辑(中右左),最后反转结果数组;
  3. 复杂度:时间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;
    }
};

关键点回顾

  1. 前序核心:根先处理,栈“先右后左”入栈,保证出栈是“左→右”;
  2. 中序核心:指针负责“访问”(遍历到左底),栈负责“处理”(弹栈存值),分离访问与处理逻辑;
  3. 后序核心:复用前序逻辑得到“中右左”,反转数组即得“左右中”,无需单独设计复杂逻辑。

102.107.199.637.429.515.116.117.104.111二叉树迭代/递归层序遍历

  1. 核心思路
    • 迭代法(BFS):用队列实现,每次处理当前层所有节点(通过que.size()固定层大小),按层收集结果;
    • 递归法(DFS):用depth标记当前层数,按层将节点值存入结果数组;
  2. 关键细节:迭代法中必须用固定size遍历当前层(避免队列动态变化导致遍历不全);
  3. 复杂度:时间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;
    }
};

核心总结

  1. 迭代法
    • 核心是queue+固定levelSize,确保每层节点被完整遍历;
    • 是层序遍历的“标准模板”,适配所有层序相关题目(如右视图、层平均值)。
  2. 递归法
    • 核心是depth标记层数,通过res.size() == depth新增层数组;
    • 本质是DFS的变形,通过深度映射层数,逻辑更抽象但代码简洁。

两份代码完全独立,可直接复制使用,符合你“分开写”的要求,再次抱歉之前的整合错误!

关键点回顾

  1. 迭代法核心:levelSize = que.size() 固定当前层节点数,确保内层循环只处理当前层,避免队列动态添加子节点导致遍历越界;
  2. 递归法核心:用depth标记层数,res.size() == depth时新增层数组,保证节点值存入对应层;
  3. 模板复用性:此迭代法代码可直接适配“层序遍历II、右视图、层平均值”等题目,仅需修改“层结果的处理逻辑”(如反转、取最后一个元素、求平均)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值