当前位置:

首页 > 编程开发 > Java二叉树的递归和非递归遍历方法是什么

Java二叉树的递归和非递归遍历方法是什么

前言二叉树的遍历方法分为前序遍历,中序遍历,后续遍历,层序遍历。1.递归遍历对于递归,就不得不说递归三要素:以前序遍历为例递归入参参数和返回值因为要打印出前序遍历节点的数值,所以参数里需要传入List在放节点的数值,除了这一点就不需要在处理什么数据了也不需要有返回值,所以递归函数返回类型就是void,代码如下:publicvoidpreorder(TreeNoderoot,Listresult)确定终止条件在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要要结束了,所以如果

本文目录

    前言

    二叉树的遍历方法分为前序遍历,中序遍历,后续遍历,层序遍历。

    Java二叉树的递归和非递归遍历方法是什么

    1.递归遍历

    对于递归,就不得不说递归三要素:以前序遍历为例

    递归入参参数和返回值

    因为要打印出前序遍历节点的数值,所以参数里需要传入List在放节点的数值,除了这一点就不需要在处理什么数据了也不需要有返回值,所以递归函数返回类型就是void,代码如下:

    public void preorder(TreeNode root, List result)

    确定终止条件

    在递归的过程中,如何算是递归结束了呢,当然是当前遍历的节点是空了,那么本层递归就要要结束了,所以如果当前遍历的这个节点是空,就直接return

    if (root == null) return;

    单层循环逻辑

    前序遍历是中左右的循序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下:

    result.add(root.val);
    preorder(root.left, result);
    preorder(root.right, result);
    // 前序遍历·递归·LC144_二叉树的前序遍历
    class Solution {
        public List preorderTraversal(TreeNode root) {
            List result = new ArrayList();
            preorder(root, result);
            return result;
        }
        public void preorder(TreeNode root, List result) {
            if (root == null) {
                return;
            }
            result.add(root.val);//先保存中间节点
            preorder(root.left, result); //处理左边节点
            preorder(root.right, result); //处理右边节点
        }
    }
    // 中序遍历·递归·LC94_二叉树的中序遍历
    class Solution {
        public List inorderTraversal(TreeNode root) {
            List res = new ArrayList<>();
            inorder(root, res);
            return res;
        }
        void inorder(TreeNode root, List list) {
            if (root == null) {
                return;
            }
            inorder(root.left, list); //先处理左边节点
            list.add(root.val);       //保存中间当前的节点
            inorder(root.right, list);//先处理右边节点
        }
    }
    // 后序遍历·递归·LC145_二叉树的后序遍历
    class Solution {
        public List postorderTraversal(TreeNode root) {
            List res = new ArrayList<>();
            postorder(root, res);
            return res;
        }
        void postorder(TreeNode root, List list) {
            if (root == null) {
                return;
            }
            postorder(root.left, list);  //先处理左边节点
            postorder(root.right, list); //再处理右边节点
            list.add(root.val);          //保存最后  
        }
    }

    2.非迭代遍历

    //前序遍历
    class Solution {
        public List preorderTraversal(TreeNode root) {
            List res = new ArrayList<>();
            Stack stack = new Stack();
            if (root == null) return res;
            stack.push(root);
            while (!stack.isEmpty()) {
                TreeNode node = stack.pop();
                res.add(node.val);
                if (node.right != null) { //先将右孩子入栈,因为它在最后
                    stack.push(node.right);
                }
                if (node.left != null) { //左孩子入栈再出栈
                    stack.push(node.left);
                }
            }
            return res;
        }
    }
    //中序遍历
    class Solution {
        public List inorderTraversal(TreeNode root) {
            List res = new ArrayList<>();
            if (root == null) return res;
            Stack stack = new Stack();
            TreeNode cur = root;
            while (cur != null || !stack.isEmpty()) {
                //如果可以,一直往左下探
                if (cur != null) {
                    stack.push(cur);
                    cur = cur.left;
                } else {
                    cur = stack.pop(); //弹出来的肯定是叶子节点或中间节点
                    res.add(cur.val); //将这个节点加入list
                    cur = cur.right; //查看当前节点是否有右节点,如果右,肯定是中间节点,如果没有,就是叶子节点,继续弹出就可以
                }
            }
            return res;
        }
    }
    //后序遍历
    //再来看后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中
    class Solution {
        public List postorderTraversal(TreeNode root) {
            List res = new ArrayList<>();
            if (root == null) return res;
            Stack stack = new Stack();
            stack.push(root);
            while (!stack.isEmpty()) {
                TreeNode node = stack.pop();
                res.add(node.val);
                if (node.left != null) stack.push(node.left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
                if (node.right != null) stack.push(node.right);// 空节点不入栈 
            }
            Collections.reverse(res); // 将结果反转之后就是左右中的顺序了
            return res;
        }
    }

    3.二叉树的统一迭代法

    //前序遍历
    class Solution {
        public List preorderTraversal(TreeNode root) {
            List result = new LinkedList<>();
            Stack st = new Stack<>();
            if (root != null) st.push(root);
            while (!st.empty()) {
                TreeNode node = st.peek();
                if (node != null) {
                    st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                    if (node.right!=null) st.push(node.right);  // 添加右节点(空节点不入栈)
                    if (node.left!=null) st.push(node.left);    // 添加左节点(空节点不入栈)
                    st.push(node);                          // 添加中节点
                    st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
                } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                    st.pop();           // 将空节点弹出
                    node = st.peek();    // 重新取出栈中元素
                    st.pop();
                    result.add(node.val); // 加入到结果集
                }
            }
            return result;
        }
    }
    //中序遍历
    class Solution {
        public List inorderTraversal(TreeNode root) {
            List result = new LinkedList<>();
            Stack st = new Stack<>();
            if (root != null) st.push(root);
            while (!st.empty()) {
                TreeNode node = st.peek();
                if (node != null) {
                    st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                    if (node.right!=null) st.push(node.right);  // 添加右节点(空节点不入栈)
                    st.push(node);                          // 添加中节点
                    st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
                    if (node.left!=null) st.push(node.left);    // 添加左节点(空节点不入栈)
                } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                    st.pop();           // 将空节点弹出
                    node = st.peek();    // 重新取出栈中元素
                    st.pop();
                    result.add(node.val); // 加入到结果集
                }
            }
            return result;
        }
    }
    //后序遍历
    class Solution {
        public List postorderTraversal(TreeNode root) {
            List result = new LinkedList<>();
            Stack st = new Stack<>();
            if (root != null) st.push(root);
            while (!st.empty()) {
                TreeNode node = st.peek();
                if (node != null) {
                    st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                    st.push(node);                          // 添加中节点
                    st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
                    if (node.right!=null) st.push(node.right);  // 添加右节点(空节点不入栈)
                    if (node.left!=null) st.push(node.left);    // 添加左节点(空节点不入栈)         
                } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                    st.pop();           // 将空节点弹出
                    node = st.peek();    // 重新取出栈中元素
                    st.pop();
                    result.add(node.val); // 加入到结果集
                }
            }
            return result;
        }
    }
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。