二叉树的递归如何写

news/2024/7/20 20:08:44 标签: 深度优先, 算法, 递归, 二叉树, 数据结构

大家好,我是三叔,很高兴这期又和大家见面了,一个奋斗在互联网的打工人。

笔者在一文读懂二叉树中有介绍到二叉树深度优先搜索中讲到:前序遍历、中序遍历、后续遍历,今天我就用代码的形式给大家展示出来。

首先大家需要了解递归的原理

递归的底层实现

递归遍历的底层原理涉及到函数调用 的概念。当一个函数在递归调用自身时,每一次递归调用都会创建一个新的函数调用帧并将其压入函数调用栈中。当递归调用结束时,对应的函数调用帧会从栈中弹出,恢复到上一次的函数调用点,然后继续执行后续的代码。

对于二叉树递归遍历(如前序遍历、中序遍历、后序遍历),递归函数的基本思想是:

  1. 在每一次递归调用中,首先处理当前节点。
  2. 然后递归调用自身来处理当前节点的左子树。
  3. 最后递归调用自身来处理当前节点的右子树。

递归遍历的过程可以理解为对树进行深度优先搜索(DFS)。当递归到达叶子节点(没有子节点)时,递归调用会返回到上一层,并继续处理上一层节点的右子树(如果存在)。

在底层实现中,每一次递归调用会将当前节点的信息(如引用或指针)和其他必要的状态(如遍历的进度、临时变量等)保存在函数调用帧中。这些帧按照调用顺序存储在函数调用栈中。

递归遍历的结束条件通常是当当前节点为空(null)时,即遍历到了树的底部。在这种情况下,递归调用会返回到上一层,并继续处理上一层的右子树或结束整个遍历过程。

需要注意的是,递归遍历可能导致函数调用栈的深度增加,因此在处理大规模树或深度嵌套的情况下,可能会面临栈溢出的风险。为了避免这种情况,可以使用迭代的方式替代递归实现。

二叉树的前序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
 // 力扣的#144题
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();// 构造一个List返回
        traversalPrev(root, result);// 递归方法
        return result;

    }

    private void traversalPrev(TreeNode root, List<Integer> result) {
    	// 当前遍历的节点一直到最底部,当左右孩子或者根节点为null的时候,结束循环,退出递归
    	// 这里很重要,如果没有准确的掌握递归结束的条件,很容易就会造成栈溢出
        if(root == null) {
            return;
        }
        // 前序遍历 中左右
        result.add(root.val);
        traversalPrev(root.left, result);
        traversalPrev(root.right, result);
    }
}

二叉树的中序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
 // 力扣#94
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        traveraslMid(root, result);
        return result;
    }
	// 中序遍历的递归
    private void traveraslMid(TreeNode root, List<Integer> result) {
        if(root == null) {
            return ;
        }
        // 中序遍历:左中右
        traveraslMid(root.left, result);
        result.add(root.val);
        traveraslMid(root.right, result);
    }
}

二叉树的后序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
 // 力扣145
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        traversalAfter(root, result);
        return result;
    }

    private void traversalAfter(TreeNode root, List<Integer> result) {
        if(root == null) {
            return ;
        }
        traversalAfter(root.left, result);// 左
        traversalAfter(root.right, result);// 右
        result.add(root.val);// 中
    }
}

http://www.niftyadmin.cn/n/421257.html

相关文章

基于山景BP10128音频处理器高通滤波器算法设计

+ hezkz17进数字音频答疑 山景BP10128音频处理器是一款高性能的数字信号处理器,专门用于音频信号的处理和增强。它采用先进的数字信号处理技术和算法,能够对音频信号进行实时处理,并且具有高效、稳定、可靠等特点。 该处理器具有以下主要功能: 均衡器:支持低音、中音、…

【024】C++对C的扩展之命名空间namespace详解

C对C的扩展 引言一、面向对象编程概述1.1、面向过程1.2、面向对象 二、作用域运算符 :: &#xff08;双冒号&#xff09;三、命名空间 namespace3.1、命名空间使用语法3.2、using声明命名空间中的成员可用3.3、using声明整个命名空间可用 总结 引言 &#x1f4a1; 作者简介&…

对数据进行模糊匹配搜索(动态规划、最长公共子串、最长公共子序列)

在搜索时常常在输入一半或者输入错误时&#xff0c;搜索引擎就给出智能提示。 已知的搜索推荐主要包括以下几个方面&#xff1a; 包含&#xff1a;“清华” 和 “清华大学”相似&#xff1a;“聊天软件” 和 “通讯软件”相关&#xff1a;“明星” 和 “刘亦菲”纠错&#xff…

【Flutter 布局】001-Flex 布局

【Flutter 布局】001-Flex 布局 文章目录 【Flutter 布局】001-Flex 布局一、Flex1、概述简介构造函数 2、基本使用代码示例运行结果 3、方向取值范围代码示例 4、水平方向&#xff1a;主轴对齐方式取值范围代码示例运行结果 5、垂直方向&#xff1a;主轴对齐方式代码示例运行结…

Java蓝桥杯

目录 往年真题 题目分类 搜索 动态规划 并查集 贪心算法 二分查找 输入输出 图论 其他 往年真题 2022年第十三届蓝桥杯大赛软件类决赛Java研究生组真题 - 题库 - C语言网 2021年蓝桥杯第十二届省赛及国赛真题 - 题库 - C语言网 2020年蓝桥杯第十一届省赛及国赛真题…

权限验证-JWT认证

JWT 1. 什么是JWT&#xff1f; JSON Web Token&#xff0c;通过数字签名的方式&#xff0c;以JSON对象为载体&#xff0c;在不同的服务终端之间安全的传输信息&#xff1b; 2. JWT有什么用&#xff1f; JWT最常见的场景就是授权认证&#xff0c;一旦用户登录&#xff0c;后…

sh、bash 和 dash 几种 shell 的区别是什么?

在调试基于 Debian 的 Docker 镜像时&#xff0c;进入容器后在终端中按上箭头键后终端显示^[[A&#xff0c;下箭头显示^[[B&#xff0c;右箭头显示^[[C&#xff0c;左箭头显示^[[D&#xff0c;按删除键也是显示了几个特殊字符。很奇怪&#xff0c;仔细看了一下&#xff0c;原来…

MySQL数据库基础 09

第九章 子查询 1. 需求分析与问题解决1.1 实际问题1.2 子查询的基本使用1.3 子查询的分类 2. 单行子查询2.1 单行比较操作符2.2 代码示例2.3 HAVING 中的子查询2.4 CASE中的子查询2.5 子查询中的空值问题2.5 非法使用子查询 3. 多行子查询3.1 多行比较操作符3.2 代码示例3.3 空…