二叉树遍历详解

article/2025/9/22 5:29:29

二叉树的遍历方式是最基本,也是最重要的一类题目,我们将从「前序」、「中序」、「后序」、「层序」四种遍历方式出发,总结他们的递归和迭代解法。

一、二叉树定义
      二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。简单来说,就是一个包含节点,以及它的左右孩子的一种数据结构

假设二叉树的节点定义如下

public class TreeNode {public int val;public TreeNode left;public TreeNode right;public TreeNode() {}public TreeNode(int val) {this.val = val;}public TreeNode(int val, TreeNode left, TreeNode right) {this.val = val;this.left = left;this.right = right;}
}

二、层序遍历

层序遍历比较简单,按照从上到下,从左到右的顺序逐次遍历。此处借用队列的先入先出特性来实现,具体代码如下

public static void levelTraverse(TreeNode root) {if (root == null) {return;}Queue<TreeNode> queue = new LinkedList<>();//初始化时把root放入队列queue.offer(root);while (!queue.isEmpty()) {TreeNode node = queue.poll();//打印节点的值System.out.print(node.val + " ");//队列是先入先出,所以此处先遍历左节点if (node.left != null) {queue.offer(node.left);}if (node.right != null) {queue.offer(node.right);}}}

三、前序遍历(根节点,左子树,右子树)

1、递归实现:二叉树遍历的递归形式比较容易实现,直接按照根节点,左子树,右子树的顺序 逐次遍历即可

private static void preOrderTraversal0(TreeNode root) {if (root == null) {return;}//打印根节点System.out.print(root.val + " ");//打印左节点preOrderTraversal0(root.left);//打印右节点preOrderTraversal0(root.right);}

2、迭代实现

2.1 迭代解法一

过程如下:

  • 初始化栈,并将根节点入栈;
  • 当栈不为空时:
    弹出栈顶元素 node,并将值添加到结果中;
    如果 node 的右子树非空,将右子树入栈;
    如果 node 的左子树非空,将左子树入栈;
    由于栈是“先进后出”的顺序,所以入栈时先将右子树入栈,这样使得前序遍历结果为 “根->左->右”的顺序。

经过上面图的讲解,代码就比较简单,代码如下:

private static void preOrderTraversal1(TreeNode root) {if (null == root) {return;}//定义一个栈方便后续遍历Stack<TreeNode> stack = new Stack<>();//初始化stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();//每一次出栈都打印节点的值System.out.print(node.val + " ");//栈是先进后出的,所以先处理右子树入栈,再左子树入栈if (node.right != null) {stack.push(node.right);}if (node.left != null) {stack.push(node.left);}}}

2.2 迭代解法二

(1)思路稍有不同,先定义一个节点cur指向root节点,先将cur节点和所有的左孩子入栈同时打印出cur节点的值,直至 cur 为空,用一个 while 循环实现。

(2)随后出栈一个节点,定义为node,执行 cur = node.right,随后继续执行 操作(1)

经过上面分析,代码中的(1)和(2)分别对应上述的描述,代码如下:

private static void preOrderTraversal2(TreeNode root) {if (root == null) {return;}Stack<TreeNode> stack = new Stack<>();//定义一个cur指向rootTreeNode cur = root;while (!stack.isEmpty() || cur != null) {//(1)只要cur!=null,则打印值,同时cur入栈,同时设置cur = cur.leftwhile (cur != null) {System.out.print(cur.val + " ");stack.push(cur);cur = cur.left;}//(2)如果cur == null,则出栈一个节点,同时设置cur = node.right,同时继续执行(1)TreeNode node = stack.pop();cur = node.right;}}

四、中序遍历(左子树,根节点,右子树)

1、递归实现:二叉树遍历的递归形式比较容易实现,直接按照(左子树,根节点,右子树)的顺序 逐次遍历即可

//中序遍历private static void inOrderTraversal0(TreeNode root) {if (root == null) {return;}//打印左节点inOrderTraversal0(root.left);//打印根节点System.out.print(root.val + " ");//打印右节点inOrderTraversal0(root.right);}

2、迭代解法:(左子树,根节点,右子树)

(1)与前序遍历的逻辑差不多,前序遍历是入栈的时候打印值,但是中序遍历是先处理左节点,再处理根节点,最后遍历右节点,所以遍历时不打印值,出栈时打印值,先定义一个节点cur指向root节点,先将cur节点和所有的左孩子入栈 直至 cur 为空,用一个 while 循环实现。

(2)随后出栈一个节点,定义为node,打印节点的值,执行 cur = node.right,随后继续执行 操作(1)

经过上面处理后 root 节点的左子树处理完毕,接下来继续处理右子树,也是重复的过程,经过上面分析,代码如下:

private static void inOrderTraversal1(TreeNode root) {if (root == null) {return;}TreeNode cur = root;Stack<TreeNode> stack = new Stack<>();while (!stack.isEmpty() || cur != null) {//(1)如果cur不等于空,一直入栈,同时执行cur = cur.left,目的是找到最左节点while (cur != null) {stack.push(cur);cur = cur.left;}//(2)如果cur为空,则出栈一个元素,同时打印值,接下来处理右子树,右子树也是调用(1)同步处理TreeNode node = stack.pop();System.out.print(node.val + " ");cur = node.right;}}

五、后续遍历(左子树,右子树,根节点)

1、递归实现:二叉树遍历的递归形式比较容易实现,直接按照(左子树,右子树,根节点)的顺序 逐次遍历即可

private static void postOrderTraversal0(TreeNode root) {if (root == null) {return;}//打印左节点postOrderTraversal0(root.left);//打印右节点postOrderTraversal0(root.right);//打印根节点System.out.print(root.val + " ");}

2、迭代实现:(二叉树的后续遍历,先左子树,右子树,最后根结点),可以定义两个辅助栈,一个栈用于辅助遍历,一个栈用于存放结果,从root开始遍历时先遍历到跟结点,但是根节点又需要最后输出,所以可以借助栈的(先进后出的)特性实现先进入的节点最后输出

经过上面的图解代码如下:

public static void postOrderTraversal(TreeNode root) {if (root == null) {return;}Stack<TreeNode> stack1 = new Stack<TreeNode>();//起始时root入栈stack1.push(root);//定义一个result栈Stack<TreeNode> result = new Stack<TreeNode>();while (!stack1.isEmpty()) {TreeNode node = stack1.pop();result.push(node);//先左节点入栈if (node.left != null) {stack1.push(node.left);}//再右节点入栈if (node.right != null) {stack1.push(node.right);}}//最后result栈中依次出栈即为结果while (!result.isEmpty()) {System.out.print(result.pop().val + " ");}}

上面仅记录个人的理解。有错误麻烦指正,感谢。


http://chatgpt.dhexx.cn/article/TUaNhtkQ.shtml

相关文章

讲透学烂二叉树(三):二叉树的遍历图解算法步骤及JS代码

二叉树的遍历是指不重复地访问二叉树中所有结点&#xff0c;主要指非空二叉树&#xff0c;对于空二叉树则结束返回。 二叉树的遍历分为 深度优先遍历 先序遍历&#xff1a;根节点->左子树->右子树&#xff08;根左右&#xff09;&#xff0c;有的叫&#xff1a;前序遍历…

二叉树的中序遍历算法(Java三种实现方法)

文章目录 题目一、二叉树的节点定义二、三种遍历方法1.递归算法思想 2.迭代算法思想 3.Morris 中序遍历算法思想 总结 题目 给定一个二叉树的根节点 root &#xff0c;返回它的 中序 遍历 一、二叉树的节点定义 public class TreeNode {int val;TreeNode left;TreeNode righ…

二叉树遍历的几种常见方法

二叉树的遍历方法 一.二叉树分类&#xff1a; 完全二叉树满二叉树扩充二叉树平衡二叉树 二.二叉树的四种遍历方式&#xff1a; 前序遍历&#xff08;先根&#xff0c;再左&#xff0c;最后右&#xff09;中序遍历&#xff08;先左&#xff0c;再根&#xff0c;最后右&#…

二叉树的三种遍历方式

目录 1.二叉树的结构&#xff1a; 2.二叉树的前序遍历&#xff1a; 3.二叉树的中序遍历&#xff1a; 4.二叉树的后序遍历&#xff1a; 5.二叉树前、中、后序的代码实现&#xff1a; 前序遍历函数&#xff1a; 中序遍历函数&#xff1a; 后序遍历&#xff1a; 完整代码&am…

图解二叉树的三种遍历

1、二叉树的遍历 前序遍历&#xff1a;根结点 —> 左子树 —> 右子树 中序遍历&#xff1a;左子树—> 根结点 —> 右子树 后序遍历&#xff1a;左子树 —> 右子树 —> 根结点 层次遍历&#xff1a;仅仅需按层次遍历就可以 前序遍历&#xff1a;1 2 4 5 7…

二叉树的遍历【 详细讲解 】

二叉树的遍历 一共有4种遍历 先看图&#xff0c;对于这个图进行4种遍历的讲解 1、 先序遍历 定义&#xff1a;若二叉树为空&#xff0c;则空操作&#xff1b;否则 &#xff08;1&#xff09;访问根节点&#xff08;2&#xff09;先序遍历左子树&#xff08;3&#…

二叉树的创建及遍历方法

目录 1、二叉树的定义及特点 2、满二叉树和完全二叉树的概念 3、二叉树的存储结构 4、创建二叉树 5、树的四种遍历方法 6、结果及其分析 1、二叉树的定义及特点 二叉树是指树中节点的度不大于2的有序树&#xff0c;它是一种最简单且最重要的树。二叉树的递归定义为&#…

二叉树遍历(图解)

二叉树的顺序存储结构就是用一维数组存储二叉树中的节点&#xff0c;并且节点的存储位置&#xff0c;也就是数组的下标要能体现节点之间的逻辑关系。—–>一般只用于完全二叉树 链式存储—–>二叉链表 定义&#xff1a; lchild | data | rchild&#xff08;两个指针域&…

图解二叉树及二叉树遍历

二叉树及二叉树遍历 完全二叉树二叉树的遍历遍历的性质 1、完全二叉树 对于一棵具有n个节点的二叉树&#xff08;按层序编号&#xff09;&#xff0c;如果编号为i的节点与同样深度的满二叉树中编号为i的节点在二叉树的位置完全相同&#xff0c;则为完全二叉树。 换句话来说&a…

数据结构--二叉树遍历(详细过程)

目录 一、什么是二叉树&#xff1f; 二、二叉树的遍历 1. 先序遍历 2. 中序遍历 3.后序遍历 4. 遍历的推导 三、重要的事情 一、什么是二叉树&#xff1f; 1. 二叉树&#xff1a;一种树形结构&#xff0c;特点是每个结点至多只有两颗子树&#xff0c;并且子树有左右之分…

图解法:三分钟掌握二叉树的三种遍历

二叉树作为树中的一种特殊存在机制&#xff0c;人们对于它的排序总结出来了三种方式&#xff0c;让我们一起探寻它的魅力吧&#xff01; 测试对象 1.先序遍历 首先看一下排序规则 先访问根节点 再先序访问左子树 再先序访问右子树 看上面的素材&#xff0c;得知根节点为…

二叉树的各种遍历算法以及实例

一、二叉树 在计算机科学中&#xff0c;树是一种重要的非线性数据结构&#xff0c;直观地看&#xff0c;它是数据元素&#xff08;在树中称为结点&#xff09;按分支关系组织起来的结构。二叉树是每个节点最多有两个子树的有序树。通常子树被称作“左子树”&#xff08;left s…

二叉树的四种遍历方法(前序遍历、中序遍历、后序遍历、层序遍历)有图有真相!!!

文章目录 二叉树的四种遍历方式前序遍历&#xff08;Preorder Traversal&#xff09;中序遍历&#xff08;Inorder Traversal&#xff09;后序遍历&#xff08;Postorder Traversal&#xff09;层序遍历&#xff08;Level Order Traversal&#xff09; 二叉树的四种遍历方式 相…

二叉树的层次遍历算法

前面学的二叉树的遍历是把二叉树看作3个部分&#xff1a;根&#xff0c;左子树&#xff0c;右子树&#xff0c;然后我们以此来访问3个部分 而层次遍历是把树看成从上到下的若干层&#xff1a;根结点在第一层&#xff0c;根结点的孩子在第二层&#xff0c;根结点的孩子的孩子在第…

二叉树各种遍历算法

二叉树是许多算法题的常用结构&#xff0c;其遍历算法的各种变种就是各种题目。具体的顺序如下&#xff1a; 先序遍历&#xff1a;先根、后左、再右中序遍历&#xff1a;先左、后根、再右后序遍历&#xff1a;先左、后右、再根 递归版先序、中序、后序遍历 最简单、最直接的…

带你图解二叉树的多种递归遍历(建议收藏!!)

文章目录 二叉树的构建结点类型的定义构建二叉树之间的关系 深度优先遍历前序遍历代码实现图解递归&#xff08;由于图片大小问题&#xff0c;建议用手机客户端查看&#xff0c;以下图解也是&#xff09; 中序遍历代码实现图解递归 后序遍历代码实现图解递归 广度优先遍历层序遍…

二叉树遍历之图解Mirror算法(莫里斯算法)

144. 二叉树的前序遍历 我们写二叉树的遍历时&#xff0c;一般有两种方式&#xff0c;迭代和递归。然而还有一种神奇的算法&#xff0c;也可以作我们的二叉树递归&#xff0c;且空间复杂度为O(1)&#xff0c;要知道&#xff0c;我们迭代和递归都是需要额外栈空间的 递归和迭代网…

二叉树遍历方法——前、中、后序遍历(图解)

目录 一、前序遍历 &#xff08;1&#xff09;递归版本 &#xff08;2&#xff09;非递归版本 二、中序遍历 &#xff08;1&#xff09;递归版本 &#xff08;2&#xff09;非递归版本 三、后序遍历 &#xff08;1&#xff09;递归版本 &#xff08;2&#xff09;非递归版…

详细图解二叉树四种遍历(前序中序后序层次遍历)

文章目录 一.前序遍历常规操作简单方法 二.中序遍历常规操作简单方法 三.后序遍历常规操作 四.层次遍历常规操作 本文中以此二叉树为例 一.前序遍历 常规操作 先根&#xff0c;再左&#xff0c;再右 确定了遍历整体结构&#xff1a; 确定了左子树中的整体结构 继续操作&…

FPN细节剖析以及pytorch代码实现

目录 FPN&#xff08;feature pyramid network&#xff09; 网络结构 bottleneck pytorch代码实现 公式&#xff1a;卷积层输入输出大小的计算公式 细节一&#xff1a;代码中blocks参数的含义 细节二&#xff1a;c1 c2 c3 c4 c5层尺寸分别为原图的1/2 1/4 1/8 1/16 1/32…