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

二叉树递归遍历与剪枝算法详解

深入讲解二叉树深度优先遍历(DFS)在算法题中的应用。内容包括布尔二叉树求值、根到叶路径数字之和、二叉树剪枝及二叉搜索树第 K 小元素查找。通过递归实现前序、后序及中序遍历,分析子节点与父节点状态依赖关系,提供 C++ 代码实现与思路解析。

MqEngine发布于 2026/3/28更新于 2026/10/2696 浏览
二叉树递归遍历与剪枝算法详解

二叉树递归遍历与剪枝算法详解

1. 前言

深度优先遍历(DFS,全称为 Depth First Traversal)是树或图结构中常用的遍历算法。该算法会尽可能深地搜索树或图的分支,直到一条路径上的所有节点都被遍历完毕,然后再回溯到上一层,继续寻找其他路径。

在二叉树中,常见的深度优先遍历包括:前序遍历、中序遍历以及后序遍历。由于树的定义本身是递归定义,采用递归的方法实现这三种遍历不仅容易理解,而且代码简洁。前、中、后序三种遍历的唯一区别在于访问根节点的时机不同。选择合适的遍历顺序对算法理解非常有帮助。

2. 计算布尔二叉树的值

题目链接:计算布尔二叉树的值

题目介绍

给你一棵完整二叉树的根,这棵树有以下特征:

  • 叶子节点要么值为 0 要么值为 1,其中 0 表示 False,1 表示 True。
  • 非叶子节点要么值为 2 要么值为 3,其中 2 表示逻辑或 OR,3 表示逻辑与 AND。

计算一个节点的值方式如下:

  • 如果节点是个叶子节点,那么节点的值为它本身,即 True 或者 False。
  • 否则,计算两个孩子的节点值,然后将该节点的运算符对两个孩子值进行运算。

返回根节点 root 的布尔运算值。

算法思路

  1. 对于规模为 n 的问题,需要求得当前节点值。
  2. 节点值不为 0 或 1 时,规模为 n 的问题可以被拆分为规模为 n-1 的子问题:
    • 获取所有子节点的值;
    • 通过子节点的值运算出当前节点值。
  3. 当问题的规模变为 n=1 时(即叶子节点的值为 0 或 1),可以直接获取当前节点值。

递归函数流程

  1. 当前问题规模为 n=1 时,即叶子节点,直接返回当前节点值。
  2. 递归求得左右子节点的值。
  3. 判断当前节点的逻辑运算符,计算左右子节点值运算得出的结果。

代码示例

class Solution {
public:
    bool evaluateTree(TreeNode* root) {
        if (root->left == nullptr || root->right == nullptr) {
            return root->val;
        } else {
            if (root->val == 2) return evaluateTree(root->left) || evaluateTree(root->right);
            else return evaluateTree(root->left) && evaluateTree(root->right);
        }
    }
};

3. 求根节点到叶节点数字之和

题目链接:求根节点到叶节点数字之和

题目介绍

给你一个二叉树的根节点 root,树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字:例如,从根节点到叶节点的路径 1->2->3 表示数字 123。 计算从根节点到叶节点生成的所有数字之和。

解题思路

解法(DFS-前序遍历):

前序遍历按照根节点、左子树、右子树的顺序遍历二叉树的所有节点,通常用于子节点的状态依赖于父节点状态的题目。

在前序遍历的过程中,我们可以往左右子树传递信息,并且在回溯时得到左右子树的返回值。递归函数可以帮我们完成两件事:

  • 将父节点的数字与当前节点的信息整合到一起,计算出当前节点的数字,然后传递到下一层进行递归;
  • 当遇到叶子节点的时候,就不再向下传递信息,而是将整合的结果向上一直回溯到根节点。在递归结束时,根节点需要返回的值也就被更新为了整棵树的数字和。

递归函数流程

  1. 当遇到空节点的时候,说明这条路从根节点开始没有分支,返回 0。
  2. 结合父节点传下的信息以及当前节点的 val,计算出当前节点数字 sum。
  3. 如果当前结点是叶子节点,直接返回整合后的结果 sum。
  4. 如果当前结点不是叶子节点,将 sum 传到左右子树中去,得到左右子树中节点路径的数字和,然后相加后返回结果。

代码示例

class Solution {
public:
    int sumNumbers(TreeNode* root) {
        return sumNumber(root, 0);
    }

private:
    int sumNumber(TreeNode* root, int x) {
        if (root == nullptr) return x;
        x = x * 10 + root->val;
        if (root->left != nullptr && root->right != nullptr) return sumNumber(root->left, x) + sumNumber(root->right, x);
        else if (root->left != nullptr) return sumNumber(root->left, x);
        else if (root->right != nullptr) return sumNumber(root->right, x);
        else return x;
    }
};

4. 二叉树剪枝

题目链接:二叉树剪枝

题目介绍

给你二叉树的根结点 root,此外树的每个结点的值要么是 0,要么是 1。 返回移除了所有不包含 1 的子树的原二叉树。 节点 node 的子树为 node 本身加上所有 node 的后代。

解题思路

解法(DFS-后序遍历):

后序遍历按照左子树、右子树、根节点的顺序遍历二叉树的所有节点,通常用于父节点的状态依赖于子节点状态的题目。

后序遍历的主要流程:

  1. 递归出口:当传入节点为空时,不做任何处理。
  2. 递归处理左子树。
  3. 递归处理右子树。
  4. 处理当前节点:判断该节点是否为叶子节点(即左右子节点均被删除,节点成为叶子节点),并且节点的值为 0:
    • 如果是,就删除掉;
    • 如果不是,就不做任何处理。

代码示例

class Solution {
public:
    TreeNode* pruneTree(TreeNode* root) {
        dfs(root);
        if (root->left == nullptr && root->right == nullptr && root->val == 0) return nullptr;
        else return root;
    }

private:
    bool dfs(TreeNode* root) {
        if (root) {
            if (root->left == nullptr && root->right == nullptr) return root->val;
            bool l = dfs(root->left);
            bool r = dfs(root->right);
            if (l == false) root->left = nullptr;
            if (r == false) root->right = nullptr;
            if (root->val == 0) return l || r;
            else return true;
        }
        return false;
    }
};

5. 二叉搜索树中第 k 小的元素

题目链接:二叉搜索树中第 k 小的元素

题目描述

给定一个二叉搜索树的根节点 root,和一个整数 k,请你设计一个算法查找其中第 k 小的元素(从 1 开始计数)。

解题思路

(中序遍历 + 计数器剪枝)

上述解法不仅使用大量额外空间存储数据,并且会将所有的结点都遍历一遍。 但是,我们可以根据中序遍历的过程,只需扫描前 k 个结点即可。 因此,我们可以创建一个全局的计数器 count,将其初始化为 k,每遍历一个节点就将 count--。直到某次递归的时候,count 的值等于 0,说明此时的结点就是我们要找的结果。

代码示例

class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        int flag = 0;
        dfs(root, k, flag);
        return flag;
    }

private:
    void dfs(TreeNode* root, int& k, int& flag) {
        if (root) {
            dfs(root->left, k, flag);
            k--;
            if (k == 0) flag = root->val;
            dfs(root->right, k, flag);
        }
    }
};

目录

  1. 二叉树递归遍历与剪枝算法详解
  2. 1. 前言
  3. 2. 计算布尔二叉树的值
  4. 题目介绍
  5. 算法思路
  6. 递归函数流程
  7. 代码示例
  8. 3. 求根节点到叶节点数字之和
  9. 题目介绍
  10. 解题思路
  11. 递归函数流程
  12. 代码示例
  13. 4. 二叉树剪枝
  14. 题目介绍
  15. 解题思路
  16. 代码示例
  17. 5. 二叉搜索树中第 k 小的元素
  18. 题目描述
  19. 解题思路
  20. 代码示例

更多推荐文章

查看全部
  • Elasticsearch 核心概念、Kibana 测试与 C++ 客户端封装实战
  • 科学机器学习中的物理信息神经网络(PINN):现状与展望
  • AD4630 四通道 SPI 模式配置与采集 FPGA 设计
  • OpenClaw 公网访问实战:借助 cpolar 实现随时随地远程连接
  • 使用 Web Scraper 浏览器插件爬取知乎评论数据
  • Linux 下 Tomcat 结合内网穿透实现公网访问
  • Python 数据挖掘实战:回归、分类、聚类与关联分析详解
  • Java 中操作 Redis
  • Python 与 PyCharm 环境搭建指南(Windows / macOS)
  • 通用 AI Agent 七步构建指南:从模型选择到编排逻辑
  • CCF-CSP 第 38 次认证第二题:机器人复健指南
  • FPGA 实现高速数字信号处理的设计本质与实战
  • Java 堆外内存释放核心技术:从 Unsafe 到 ByteBuffer 的完整回收链解析
  • 图灵奖得主对人工智能发展的深远影响
  • 算法实战:位运算解决两数之和与唯一数字问题
  • 常见 Web 安全技术总结与入门指南
  • JavaScript 基础知识详解
  • Mac Studio M4 通过 vLLM 部署本地大模型
  • Python 回归分析实战:从线性模型到随机森林
  • Windows 部署 OpenAkita 并接入飞书实现本地 AI 助手

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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