首页/新闻资讯/正文详情

深入理解二叉树遍历:从递归代码到调用栈

发布时间:2026/11/3 2:18:22 来源:云帆数科 栏目:资讯中心
深入理解二叉树遍历:从递归代码到调用栈
二叉树遍历要解决的问题只有一个按照什么顺序处理当前节点、左子树和右子树。左右子树本身也是二叉树所以可以用同一个函数继续处理。这就是递归。前序、中序和后序并非三种不同思想只是访问当前节点的时机不同。一、遍历顺序由访问位置决定对于任意节点递归框架都是voidtraverse(TreeNoderoot){if(rootnull){return;}// 位置一traverse(root.left);// 位置二traverse(root.right);// 位置三}访问操作放在不同位置就形成三种遍历前序根 → 左 → 右 中序左 → 根 → 右 后序左 → 右 → 根对应代码如下// 前序遍历voidpreorder(TreeNoderoot,ListIntegerresult){if(rootnull){return;}result.add(root.value);preorder(root.left,result);preorder(root.right,result);}// 中序遍历voidinorder(TreeNoderoot,ListIntegerresult){if(rootnull){return;}inorder(root.left,result);result.add(root.value);inorder(root.right,result);}// 后序遍历voidpostorder(TreeNoderoot,ListIntegerresult){if(rootnull){return;}postorder(root.left,result);postorder(root.right,result);result.add(root.value);}所以“前、中、后”描述的是根节点相对于左右子树的访问位置进入节点时访问 → 前序 左子树处理完后访问 → 中序 左右子树都处理完后访问 → 后序二、调用栈如何产生遍历顺序重点理解栈存储的是调用位置。梳理清楚前、中、后遍历时各元素是如何压栈的。使用下面的二叉树1 / \ 2 3 / \ / \ 4 5 6 7递归调用时每进入一个节点就把该节点的函数压入调用栈。子函数执行期间父函数暂停子函数返回后父函数从暂停位置继续。需要区分压栈进入函数 访问处理节点 出栈函数执行完毕访问节点不等于函数出栈。1. 前序遍历前序遍历进入节点后立即访问因此压栈路径直接形成访问顺序。进入并访问 1 栈顶 ┌──────────────┐ │ 1等待左子树 │ └──────────────┘ 栈底 输出1进入并访问 2 栈顶 ┌──────────────┐ │ 2等待左子树 │ ├──────────────┤ │ 1等待左子树 │ └──────────────┘ 栈底 输出1 2进入并访问 4 栈顶 ┌──────────────┐ │ 4正在执行 │ ├──────────────┤ │ 2等待左子树 │ ├──────────────┤ │ 1等待左子树 │ └──────────────┘ 栈底 输出1 2 44完成后出栈再进入52完成后出栈再进入3、6、7。完整访问顺序 1 → 2 → 4 → 5 → 3 → 6 → 72. 中序遍历中序遍历先进入左子树因此开始时只压栈不访问。依次进入 1、2、4 栈顶 ┌──────────────┐ │ 4等待左子树 │ ├──────────────┤ │ 2等待左子树 │ ├──────────────┤ │ 1等待左子树 │ └──────────────┘ 栈底 输出空4的左子树为空所以访问4并返回。随后恢复2访问2再进入右子树5。栈顶 ┌──────────────┐ │ 5正在执行 │ ├──────────────┤ │ 2等待右子树 │ ├──────────────┤ │ 1等待左子树 │ └──────────────┘ 栈底 输出4 → 25完成后2才能出栈。随后访问1再以相同方式处理右子树。完整访问顺序 4 → 2 → 5 → 1 → 6 → 3 → 7中序遍历的栈中保存的是左子树尚未完成或者右子树尚未处理的节点。3. 后序遍历后序遍历必须等左右子树都完成后才能访问当前节点。依次进入 1、2、4 栈顶 ┌──────────────┐ │ 4等待子树 │ ├──────────────┤ │ 2等待左子树 │ ├──────────────┤ │ 1等待左子树 │ └──────────────┘ 栈底 输出空4没有子树因此访问并出栈。接着进入并访问5。此时2的左右子树都已完成才访问2。栈顶 ┌────────────────┐ │ 2左右均已完成 │ ├────────────────┤ │ 1等待左子树 │ └────────────────┘ 栈底 输出4 → 5 → 2右子树同理依次访问6、7、3。最后节点1的左右子树都完成访问1。完整访问顺序 4 → 5 → 2 → 6 → 7 → 3 → 1后序遍历体现的是依赖关系必须先得到左右子树的结果才能处理当前节点。三、完整实现与复杂度importjava.util.ArrayList;importjava.util.List;publicclassBinaryTreeTraversal{staticclassTreeNode{intvalue;TreeNodeleft;TreeNoderight;TreeNode(intvalue){this.valuevalue;}}// 前序根 - 左 - 右staticvoidpreorder(TreeNoderoot,ListIntegerresult){if(rootnull){return;}result.add(root.value);preorder(root.left,result);preorder(root.right,result);}// 中序左 - 根 - 右staticvoidinorder(TreeNoderoot,ListIntegerresult){if(rootnull){return;}inorder(root.left,result);result.add(root.value);inorder(root.right,result);}// 后序左 - 右 - 根staticvoidpostorder(TreeNoderoot,ListIntegerresult){if(rootnull){return;}postorder(root.left,result);postorder(root.right,result);result.add(root.value);}publicstaticvoidmain(String[]args){/* * 1 * / \ * 2 3 * / \ / \ * 4 5 6 7 */TreeNoderootnewTreeNode(1);root.leftnewTreeNode(2);root.rightnewTreeNode(3);root.left.leftnewTreeNode(4);root.left.rightnewTreeNode(5);root.right.leftnewTreeNode(6);root.right.rightnewTreeNode(7);ListIntegerpreorderResultnewArrayList();ListIntegerinorderResultnewArrayList();ListIntegerpostorderResultnewArrayList();preorder(root,preorderResult);inorder(root,inorderResult);postorder(root,postorderResult);System.out.println(前序遍历preorderResult);System.out.println(中序遍历inorderResult);System.out.println(后序遍历postorderResult);}}输出前序遍历[1, 2, 4, 5, 3, 6, 7] 中序遍历[4, 2, 5, 1, 6, 3, 7] 后序遍历[4, 5, 2, 6, 7, 3, 1]每个节点只被处理一次因此时间复杂度O(n) 空间复杂度O(h)其中n是节点数量h是树高。空间消耗来自递归调用栈。最终可以将三种遍历统一为一句话递归负责处理左右子树访问根节点的位置决定遍历类型访问在左递归之前是前序在左右递归之间是中序在右递归之后是后序。

相关推荐

深入 LangChain:掌握结构化输出与流式传输两大利器----《Hello LangChain LangGraph!》(4)
深入 LangChain:掌握结构化输出与流式传输两大利器----《Hello LangChain LangGraph!》(4)

文章目录结构化输出结构化输出流式传输自定义流式输出解析器结构化输出 结构化输出 聊天模型的 with_structured_output 方法允许我们预先定义一个期望的数据结构,并要求大模型必须按照这个结构返回信息。 –LangChain输出解析器则是依赖模型的文本去生成&#xff… · 2026/11/3 2:17:22

Mac 菜单栏电池状态监控:SketchyBar 电量插件实用上手
Mac 菜单栏电池状态监控:SketchyBar 电量插件实用上手

Mac 菜单栏电池状态监控:SketchyBar 电量插件实用上手 【免费下载链接】SketchyBar A highly customizable macOS status bar replacement 项目地址: https://gitcode.com/gh_mirrors/sk/SketchyBar 打开 MacBook 的盖子,视线扫到右上角的菜单栏&… · 2026/11/3 2:17:22

解决问题的思维方式 —— 第一性原理
解决问题的思维方式 —— 第一性原理

前言:今天我们不聊编程技术,给大家介绍一个解决问题的思维方式 —— 第一性原理!一、什么是第一性原理它是一种解决问题的思维方式,它强调的是通过问题的表象看到那个最基本的事实,这样,我们就能够找到问题… · 2026/11/3 2:17:22

仓库越大越乱?一家郑州五金批发商的“仓库翻身仗“
仓库越大越乱?一家郑州五金批发商的“仓库翻身仗“

一、凌晨一点,老板还在仓库里找一颗螺丝郑州某五金行业的老板,曾经有个外号叫"仓库里的夜猫子"。仓库两千平,货架一排接一排,五金工具、机电配件、紧固件加起来三万多个品项。客户一个电话要某个型号的轴承,… · 2026/11/3 2:47:27

html+css基础:30、伸缩盒模型(伸缩项目--伸/缩,flex复合属性,项目排序与单独对齐,案例)
html+css基础:30、伸缩盒模型(伸缩项目--伸/缩,flex复合属性,项目排序与单独对齐,案例)

伸缩盒模型的伸缩项目--伸/缩,flex复合属性,项目排序与单独对齐,案例等:Ⅰ、伸缩盒模型的伸缩项目--伸:flex-grow: 0;其一、代码为:其二、结果为:Ⅱ、伸缩盒模型的伸缩项目--缩:flex… · 2026/11/3 2:47:27

内网安全第一道闸:为什么你的网络总被 “陌生人“ 混进来?
内网安全第一道闸:为什么你的网络总被 “陌生人“ 混进来?

引言 做过网络 / 安全的都知道,内网失守往往不是防火墙没配好,而是门没看住—— 员工把个人手机、无线路由、不知名摄像头偷偷插进交换机,一台带病毒的工作站随意接入,双网卡电脑绕过隔离直连互联网…… 等你发现时,数… · 2026/11/3 2:47:27

FA_CNN卷积神经网络十九---模型选择、欠拟合与过拟合
FA_CNN卷积神经网络十九---模型选择、欠拟合与过拟合

FA:Formular and Algorithm,CNN:Convoluation Neural Network 1. 写在前面:为什么用多项式讲模型选择 在深度学习中,"模型选择"听起来抽象,但它的本质问题非常朴素:给定一份数据&… · 2026/11/3 2:47:27

经验丰富的汽车安装车载手机互联苹果Carplay和华为Hicar哪家专业
经验丰富的汽车安装车载手机互联苹果Carplay和华为Hicar哪家专业

最近好几个朋友都问我,车子上想装个CarPlay或者HiCar,到底去哪里弄靠谱。说真的,我太懂这种纠结了。我自己那台车,当初就是冲着车机互联去的,结果在路边店装完,先是连不上,后来好不容易连上了&a… · 2026/11/3 2:47:27

GitLab 私有化部署太吃内存:只留仓库和合并请求
GitLab 私有化部署太吃内存:只留仓库和合并请求

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 2:46:27

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18

STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59

ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59

基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码