跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

二叉树理论基础与遍历实现

二叉树的基础理论,包括满二叉树、完全二叉树等类型及存储方式。详细讲解了二叉树的四种遍历方法:递归遍历(前序、中序、后序)、迭代遍历、统一迭代法以及层序遍历。文中提供了每种方法的 C++ 代码实现,分析了递归三要素、栈的使用逻辑及统一迭代法的两种思路,帮助读者掌握二叉树遍历的核心原理与编码技巧。

莫名其妙发布于 2026/3/23更新于 2026/7/59.8K 浏览
二叉树理论基础与遍历实现

二叉树理论基础

  • 二叉树类型有:满二叉树、完全二叉树、二叉搜索树和平衡二叉搜索树。
  • 存储方式有:链式存储(指针)和顺序存储(数组)。
  • 遍历方式有:
    1. 深度优先:前中后序遍历(递归,迭代)
    2. 广度优先:层序遍历(迭代)
  • 二叉树结点的定义
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) {}
};

二叉树的递归遍历

重点

  • 二叉树的学习引入了递归的大量使用
  • 递归三要素:
    1. 确定递归函数的参数和返回值
    2. 确定终止条件
    3. 确定单层递归的逻辑
  • 递归开销大,内存占用久
C++ 实现(前序遍历)中,左,右
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        if (root == nullptr) return {};
        vector<int> result;
        (root, result);
         result;
    }
    {
         (root == ) ; 
        result.(root->val); 
        (root->left, result); 
        (root->right, result); 
        ;
    }
};
traverseTree
return
void traverseTree(TreeNode* root, vector<int>& result)
if
nullptr
return
// 终止条件
push_back
// 中
traverseTree
// 左孩子
traverseTree
// 右孩子
return
C++ 实现(中序遍历)左,中,右
class Solution {
public:
    std::vector<int> inorderTraversal(TreeNode* root) {
        std::vector<int> result;
        traverse(root, result);
        return result;
    }
private:
    void traverse(TreeNode* node, std::vector<int>& res) {
        if (node == nullptr) return; // 递归终止条件
        traverse(node->left, res); // 左
        res.push_back(node->val); // 中
        traverse(node->right, res); // 右
    }
};
C++ 实现(后序遍历)左,右,中
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        traverseTree(root, result);
        return result;
    }
    void traverseTree(TreeNode* root, vector<int>& result) {
        if (root == nullptr) return;
        traverseTree(root->left, result);
        traverseTree(root->right, result);
        result.push_back(root->val);
    }
};

二叉树的迭代遍历

重点

  • 手动实现一遍,按照实现步骤转换成代码,就理解了
  • 就是一个栈,放进放出。
  • 只用栈,所有的循环判断依靠的是栈本身。弹出顺序和使用顺序一致。
  • 中序遍历使用一个栈无法直接实现,就是因为栈顶节点和要使用节点不一致。循环判断条件依靠的是辅助指定的指针和栈本身。
C++ 实现(前序遍历)中,左,右
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == nullptr) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* temp = st.top();
            st.pop();
            result.push_back(temp->val);
            if (temp->right) st.push(temp->right);
            if (temp->left) st.push(temp->left);
        }
        return result;
    }
};
C++ 实现(中序遍历)左,中,右

一直向左走到底(入栈),遇到空就弹出栈顶(即'回溯'),访问该节点,然后转向其右子树。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != nullptr || !st.empty()) {
            if (cur != nullptr) {
                st.push(cur);
                cur = cur->left;
            } else {
                cur = st.top();
                st.pop();
                result.push_back(cur->val);
                cur = cur->right;
            }
        }
        return result;
    }
};

因为栈放进去之后,所有元素都没有区别,只有栈顶获取,弹出,所以需要另一个指针来确定栈顶的元素是否要使用。

C++ 实现(后序遍历)左,右,中
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root == nullptr) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* temp = st.top();
            st.pop();
            result.push_back(temp->val);
            if (temp->left) st.push(temp->left);
            if (temp->right) st.push(temp->right);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

二叉树的统一迭代法

重点

  • 两种方法
  • 第一种,一个节点可以处理的范围是自己和左右孩子(该节点的根,该节点处理不到)。节点分两部分完成遍历,第一次通过节点来获得左右孩子,第二次看到第一次处理过的标志直接处理本节点。
  • 第二种,给一个 pair,first 表示节点,second 表示是否使用过。
  • 本质是一种方式,就是让节点分两步进行。没处理过的先处理,处理过的直接用。
C++ 实现(前序遍历)使用 null 表示使用
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root == nullptr) return {};
        st.push(root);
        while (!st.empty()) {
            TreeNode* temp = st.top();
            if (temp) {
                st.pop();
                if (temp->right) st.push(temp->right);
                if (temp->left) st.push(temp->left);
                st.push(temp);
                st.push(nullptr);
            } else {
                st.pop();
                temp = st.top();
                st.pop();
                result.push_back(temp->val);
            }
        }
        return result;
    }
};
C++ 实现(中序遍历)使用 null 表示使用
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root == nullptr) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* temp = st.top();
            if (temp) {
                st.pop();
                if (temp->right) st.push(temp->right);
                st.push(temp);
                st.push(NULL);
                if (temp->left) st.push(temp->left);
            } else {
                st.pop();
                temp = st.top();
                st.pop();
                result.push_back(temp->val);
            }
        }
        return result;
    }
};
C++ 实现(后序遍历)使用 null 表示使用
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root == nullptr) return {};
        st.push(root);
        while (!st.empty()) {
            TreeNode* temp = st.top();
            if (temp) {
                st.push(nullptr);
                if (temp->right) st.push(temp->right);
                if (temp->left) st.push(temp->left);
            } else {
                st.pop();
                temp = st.top();
                st.pop();
                result.push_back(temp->val);
            }
        }
        return result;
    }
};
C++ 实现(中序遍历)使用 pair 携带一个 bool 来确定元素状态
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<pair<TreeNode*, bool>> st;
        if (root != nullptr) st.push(make_pair(root, false));
        while (!st.empty()) {
            auto node = st.top().first;
            auto visited = st.top().second;
            st.pop();
            if (visited) {
                result.push_back(node->val);
                continue;
            }
            if (node->right) st.push(make_pair(node->right, false));
            st.push(make_pair(node, true));
            if (node->left) st.push(make_pair(node->left, false));
        }
        return result;
    }
};

二叉树层序遍历

重点

  • 逐层
C++ 实现
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int>> result;
        if (root == nullptr) return result;
        que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            for (int i = 0; i < size; i++) {
                TreeNode* temp = que.front();
                que.pop();
                vec.push_back(temp->val);
                if (temp->left) que.push(temp->left);
                if (temp->right) que.push(temp->right);
            }
            result.push_back(vec);
        }
        return result;
    }
};

总结

  • 也是特点吧
  • 遍历的时候,如果单一使用栈或者队列,函数体内的循环逻辑围绕的就是栈或队列是否为空
  • 如果是中序迭代,遍历需要一个指针来辅助,函数体内的循环逻辑围绕的就是栈是否空以及指针是否为空
  • 这样便于记忆二叉树的遍历逻辑

目录

  1. 二叉树理论基础
  2. 二叉树的递归遍历
  3. 重点
  4. C++ 实现(前序遍历)中,左,右
  5. C++ 实现(中序遍历)左,中,右
  6. C++ 实现(后序遍历)左,右,中
  7. 二叉树的迭代遍历
  8. 重点
  9. C++ 实现(前序遍历)中,左,右
  10. C++ 实现(中序遍历)左,中,右
  11. C++ 实现(后序遍历)左,右,中
  12. 二叉树的统一迭代法
  13. 重点
  14. C++ 实现(前序遍历)使用 null 表示使用
  15. C++ 实现(中序遍历)使用 null 表示使用
  16. C++ 实现(后序遍历)使用 null 表示使用
  17. C++ 实现(中序遍历)使用 pair 携带一个 bool 来确定元素状态
  18. 二叉树层序遍历
  19. 重点
  20. C++ 实现
  21. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 前端权限管理实现方案与最佳实践
  • 区块链共识算法:时间长河(Time River Consensus Algorithm)
  • 基于人类反馈的强化学习(RLHF)全解析
  • Python 语音识别结合 Appium 实现抖音自动化操作
  • HarmonyOS 底部导航栏组件 rc_concave_tabbar 使用指南
  • 从 AI 绘图到 AI 视频:2026 内容创作者进阶之路
  • Midjourney AI 绘图工具使用指南与基础操作教程
  • 中小团队低成本搭建项目管理系统:Ubuntu 下 DooTask 私有化部署实战
  • Windows 下 MinIO 服务搭建与 Web 控制台访问指南
  • Colossal-AI 开源 LLaMA2 全流程训练微调推理方案
  • 前端微前端:大型应用的模块化解决方案
  • 数据结构初阶:顺序表、链表与时间空间复杂度
  • DownGit:GitHub 文件夹精准下载工具
  • C++ 备忘录模式:优雅实现对象状态保存与恢复
  • Windows 下 VSCode 配置 C/C++ 开发环境完整指南
  • Gazebo 机器人三维物理仿真平台详解
  • 二叉树前中后序遍历:递归与迭代实现详解
  • 单链表常见算法题解析:反转、合并与环检测
  • 使用 Java 将 PDF 转换为 Excel:基础转换与高级设置
  • Windows 环境下 Git 的下载、安装与配置指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online