算法分析之二叉树遍历

article/2025/10/8 17:31:47

算法相关数据结构总结:

序号数据结构文章
1动态规划动态规划之背包问题——01背包
动态规划之背包问题——完全背包
动态规划之打家劫舍系列问题
动态规划之股票买卖系列问题
动态规划之子序列问题
算法(Java)——动态规划
2数组算法分析之数组问题
3链表算法分析之链表问题
算法(Java)——链表
4二叉树算法分析之二叉树
算法分析之二叉树遍历
算法分析之二叉树常见问题
算法(Java)——二叉树
5哈希表算法分析之哈希表
算法(Java)——HashMap、HashSet、ArrayList
6字符串算法分析之字符串
算法(Java)——字符串String
7栈和队列算法分析之栈和队列
算法(Java)——栈、队列、堆
8贪心算法算法分析之贪心算法
9回溯Java实现回溯算法入门(排列+组合+子集)
Java实现回溯算法进阶(搜索)
10二分查找算法(Java)——二分法查找
11双指针、滑动窗口算法(Java)——双指针
算法分析之滑动窗口类问题

二叉树的基础知识已经在上一篇文章算法分析之二叉树学习过了,这篇文章主要是二叉树的遍历方式,包括递归和迭代版本。

二叉树的相关算法,如属性,操作,二叉搜索树等,请参考:算法分析之二叉树常见问题。

文章目录

      • 一、二叉树的遍历
      • 二、二叉树的递归遍历
        • 1. 二叉树的前序遍历
        • 2. 二叉树的中序遍历
        • 3. 二叉树的后序遍历
      • 三、二叉树的迭代遍历
        • 1. 二叉树的前序遍历
        • 2. 二叉树的中序遍历
        • 3. 二叉树的后序遍历
      • 四、二叉树的层序遍历
        • 1. 层序遍历的迭代实现
        • 2. leetcode关于层序遍历的算法
          • 107. 二叉树的层序遍历 II
          • 199. 二叉树的右视图

一、二叉树的遍历

二叉树的遍历方式主要有两种:

  1. 深度优先遍历(DFS):前序、中序、后续遍历
  2. 广度优先遍历(BFS):层序遍历

leetcode相关题目:

144. 二叉树的前序遍历

94. 二叉树的中序遍历

145. 二叉树的后序遍历

102. 二叉树的层序遍历

二、二叉树的递归遍历

先写一下递归的三要素:

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

1. 二叉树的前序遍历

前序遍历:根左右

class Solution {public List<Integer> preorderTraversal(TreeNode root) {// 递归版本ArrayList<Integer> res = new ArrayList<>();preOrder(root, res);return res;}public void preOrder(TreeNode root, ArrayList<Integer> res) {if(root == null) return;res.add(root.val);preOrder(root.left, res);preOrder(root.right, res);}
}

2. 二叉树的中序遍历

中序遍历:左根右

class Solution {public List<Integer> inorderTraversal(TreeNode root) {// 递归版本ArrayList<Integer> res = new ArrayList<>();inOrder(root, res);return res;}public void inOrder(TreeNode root, ArrayList<Integer> res) {if(root == null) return;inOrder(root.left, res);res.add(root.val);inOrder(root.right, res);}
}

3. 二叉树的后序遍历

后序遍历:左右根

class Solution {public List<Integer> postorderTraversal(TreeNode root) {// 递归版本ArrayList<Integer> res = new ArrayList<>();postOrder(root, res);return res;}public void postOrder(TreeNode root, ArrayList<Integer> res) {if(root == null) return;postOrder(root.left, res);postOrder(root.right, res);res.add(root.val);}
}

三、二叉树的迭代遍历

用栈来迭代实现二叉树的遍历,下面是用一个统一的模板来实现前中后序的迭代遍历,前序和中序比较简单,只需要修改加入的顺序,后续遍历稍微复杂,需要判断右节点。

1. 二叉树的前序遍历

用栈来迭代实现二叉树的前序遍历:

前序遍历是根左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。这样出栈的时候才是根左右的顺序。

在这里插入图片描述

一边把根节点和左节点加入list,一边左压栈,全部入栈后,出栈找右节点,将右节点加入list

class Solution {public List<Integer> preorderTraversal(TreeNode root) {// 非递归迭代版本,栈ArrayList<Integer> res = new ArrayList<>();Stack<TreeNode> stack = new Stack();TreeNode cur = root;while(cur != null || !stack.isEmpty()) {  while(cur != null) {  // 一直左压栈res.add(cur.val);stack.push(cur);cur = cur.left;}cur = stack.pop();cur = cur.right;}return res;}
}

2. 二叉树的中序遍历

用栈来迭代实现二叉树的中序遍历:

中序遍历是左根右。

在这里插入图片描述

class Solution {public List<Integer> inorderTraversal(TreeNode root) {// 非递归迭代版本,栈ArrayList<Integer> res = new ArrayList<>();Stack<TreeNode> stack = new Stack();TreeNode cur = root;while(cur != null || !stack.isEmpty()) {  while(cur != null) {  // 一直左压栈stack.push(cur);cur = cur.left;}cur = stack.pop();res.add(cur.val);cur = cur.right;}return res;}
}

3. 二叉树的后序遍历

用栈来迭代实现二叉树的后序遍历:

有很多写法都是把前序遍历反转来实现后序遍历,但这并不是后序遍历的迭代实现。

后序遍历稍微复杂的地方是需要设置一个节点,来保存上一个节点。遇到右节点的时候需要判断是不是上一个节点。

class Solution {public List<Integer> postorderTraversal(TreeNode root) {        // 非递归,迭代版本ArrayList<Integer> res = new ArrayList<>();Stack<TreeNode> stack = new Stack();TreeNode cur = root;TreeNode pre = null;  // 记录上一个节点,用来判断右节点是不是上一个节点while(cur != null || !stack.isEmpty()) {  while(cur != null) {  // 一直左压栈stack.push(cur);cur = cur.left;}cur = stack.peek();// 后续遍历左节点加入list,遇到根节点,判断有没有右节点,有加右节点,无加根节点// 如果是从右边返回根节点,则应该返回上层,主要判断出来是不是右子树if(cur.right == null || cur.right == pre) {res.add(cur.val);stack.pop();pre = cur;cur = null;} else {cur = cur.right;}}return res;}
}

四、二叉树的层序遍历

1. 层序遍历的迭代实现

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。

需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。

而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。

在这里插入图片描述

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {// 使用队列实现层序遍历,逐层将队列元素加入到listif(root == null) return new ArrayList<>();List<List<Integer>> res = new ArrayList<>();Queue<TreeNode> queue = new LinkedList<>();queue.add(root);while(!queue.isEmpty()) {int count = queue.size();List<Integer> list = new ArrayList<>();while(count > 0) {TreeNode node = queue.poll();list.add(node.val);if(node.left != null) {queue.add(node.left);}if(node.right != null) {queue.add(node.right);}count--;}res.add(list);}return res;}
}

2. leetcode关于层序遍历的算法

107. 二叉树的层序遍历 II

leetcode题目链接:107. 二叉树的层序遍历 II

给定一个二叉树,返回其节点值自底向上的层序遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

例如:
给定二叉树 [3,9,20,null,null,15,7],

    3/ \9  20/  \15   7

返回其自底向上的层序遍历为:

[[15,7],[9,20],[3]
]

解题思路:
这道题与 102. 二叉树的层序遍历 相同,只需要在最后输出的时候反转列表即可。

这里有几种反转列表的方法:

// 1. for循环遍历反转列表
List<List<Integer>> result = new ArrayList<>();
for (int i = res.size() - 1; i >= 0; i-- ) {result.add(res.get(i));
}
return result;
// 2. 利用LinkedList的addFirst()函数直接将list加到队首
LinkedList<List<Integer>> res = new LinkedList<>();
……
res.addFirst(list);

Java代码实现:

class Solution {public List<List<Integer>> levelOrderBottom(TreeNode root) {// 使用队列实现层序遍历,逐层将队列元素加入到list// 使用LinkedList的addFirst()LinkedList<List<Integer>> res = new LinkedList<>();// List<List<Integer>> res = new ArrayList<>();if(root == null) return res;Queue<TreeNode> queue = new LinkedList<>();queue.add(root);while(!queue.isEmpty()) {int count = queue.size();List<Integer> list = new ArrayList<>();while(count > 0) {TreeNode node = queue.poll();list.add(node.val);if(node.left != null) {queue.add(node.left);}if(node.right != null) {queue.add(node.right);}count--;}res.addFirst(list);}// // 反转列表// List<List<Integer>> result = new ArrayList<>();// for (int i = res.size() - 1; i >= 0; i-- ) {//     result.add(res.get(i));// }// return result;return res;}
}
199. 二叉树的右视图

leetcode题目链接:199. 二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

在这里插入图片描述

输入: [1,2,3,null,5,null,4]
输出: [1,3,4]

Java代码实现:

class Solution {public List<Integer> rightSideView(TreeNode root) {// 使用队列实现层序遍历,逐层将队列元素加入到listList<Integer> res = new ArrayList<>();if(root == null) return res;Queue<TreeNode> queue = new LinkedList<>();queue.add(root);while(!queue.isEmpty()) {int count = queue.size();for(int i = 0; i < count; i++) {TreeNode node = queue.poll();if(node.left != null) {queue.add(node.left);}if(node.right != null) {queue.add(node.right);}if(i == count - 1) {  // 将每一层的最后一个节点放入列表res.add(node.val);}}}return res;}
}

参考:

代码随想录:二叉树的遍历

二叉树的层序遍历


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

相关文章

二叉树遍历算法总结

A. 二叉树的遍历 1.前序遍历二叉树&#xff1a; (1)若二叉树为空&#xff0c;则为空操作&#xff0c;返回空。 (2)访问根结点。 (3)前序遍历左子树。 (4)前序遍历右子树。 a.二叉树前序遍历的递归算法&#xff1a; void PreOrderTraverse(BiTree BT)…

二叉树的遍历算法

遍历是对树的一种最基本的运算&#xff0c;所谓遍历二叉树&#xff0c;就是按一定的规则和顺序走遍二叉树的所有节点&#xff0c;使每一个节点都被访问一次&#xff0c;而且只被访问一次。由于二叉树是非线性结构&#xff0c;因此&#xff0c;树的遍历实质上是将二叉树的各个节…

【算法】二叉树遍历算法总结:前序中序后序遍历

前言 二叉树遍历是非常经典的算法题&#xff0c;也是二叉树的一道基础算法题。 但是在平常的笔试面试中&#xff0c;其出现的频率其实并不是特别的高&#xff0c;我推测是这种题目相对来说比较基础&#xff0c;算是一个基础知识点。 比如剑指offer中出现的后序遍历题目&…

二叉树遍历算法的应用

目录 一、二叉树遍历算法的应用——二叉树的创建 二、二叉树遍历算法的应用——复制二叉树 三、二叉树遍历算法的应用——计算二叉树的深度 四、二叉树遍历算法的应用——计算二叉树节点总数 五、二叉树遍历算法的应用——计算二叉树叶子节点数 一、二叉树遍历算法的应用—…

一文弄懂二叉树的三种遍历方式

关注公众号【高性能架构探索】&#xff0c;后台回复【pdf】&#xff0c;免费获取计算机必备经典书籍 俗话说&#xff1a;学如逆水行舟,不进则退;心似平原走马,易放难收。这句话对程序员而言&#xff0c;体会更深。这行已经越来越卷了&#xff0c;时刻准备着&#xff0c;&#x…

二叉树遍历算法

目录 先序遍历 中序遍历 后序遍历 层序遍历 938. 二叉搜索树的范围和 110. 平衡二叉树 114. 二叉树展开为链表 117. 填充每个节点的下一个右侧节点指针 II 116. 填充每个节点的下一个右侧节点指针 1&#xff0c;三种遍历都是先把二叉树的最左结点循环入栈(DFS迭代)&am…

二叉树的四种遍历算法(结构体数组)

一、二叉树的定义 以字符串的形式定义一棵二叉树的先序序列&#xff0c;若字符是‘#’&#xff0c;表示该二叉树是空树&#xff0c;否则该字符是相应结点的数据元素。 例&#xff1a;ABDG##HI####CE#J##F## 对应的二叉树&#xff1a; 思路讲解&#xff1a; 想要遍历二叉树&am…

二叉树的四种遍历方式

概要 树本身是一种简单化的图 &#xff1b; DFS对应前中后序遍历&#xff0c;BFS对应层序遍历 二叉树结构 struct treenode {int val;treenode *left;treenode *right;treenode() : val(0), left(nullptr), right(nullptr) {}treenode(int x) : val(x), left(nullptr), right(n…

针对Linux学习,值得阅读的五本书籍,不看可能错失机会

今天为了总结一些可以帮助各位在学习过程中提供帮助的一些书籍。 一.鸟叔的私房菜&#xff1a; 本书是知名度颇高的Linux入门书《鸟哥的Linux私房菜基础学习篇》的新版,而详细地介绍了Linux操作系统。全书分为五部分;第一部分部分着重说明计算机的基础知识、Linux的学习方法&a…

从零开始学习Linux(一)关闭虚拟机系统

关闭系统&#xff0c;需要输入如下命令 poweroff然而&#xff0c;你只能得到如下反馈 -bash: poweroff:command not found此项错误是因为poweroff命令是一个系统管理命令。执行此项命令需要高级使用者特权。 因此&#xff0c;为了关闭系统&#xff0c;我们首先需要切换到root…

个人随笔/小白应该如何学习Linux,我的一些心得分享.

大家好&#xff0c;今天给大家分享一下0基础的人如何入门Linux&#xff0c;此文来源&#xff1a;我在上班的路上看到一篇文章&#xff0c;也是写的0基础的人如何学习Linux的文章。当时我在想&#xff0c;我写博文一年多&#xff0c;都是相关Linux及Python等技术的文章&#xff…

Linux学习路线

&#xfeff;&#xfeff; 关于 Linux Linux 因其开源&#xff0c;免费&#xff0c;可裁剪&#xff0c;被应用到很多领域&#xff0c;尤其是嵌入式设备上。 Android 系统内核也是基于 Linux 的。 另外还有各种服务器和工作站也是用的 Linux。 什么是嵌入式设备&#xff1f;…

为什么要学习 Linux ????

目前企业中大量的使用Linux作为服务器&#xff0c;在以后你们就业后&#xff0c;会发现web服务器Tomcat ,jobss这一类都是搭建在linux上面的&#xff0c;后面我们需要学习的数据库mysql &#xff0c; oracle &#xff0c;db2&#xff0c; 或者greenplum这一类的&#xff0c;在企…

Linux 学习路线图

1.应用场景 更加高效地学习并达到运用Linux. 2.学习/操作 linux运维学习需要分为四个阶段&#xff1a;初级入门、中级进阶、高级提升、资深方向细化。 第一阶段&#xff1a;初级入门 初级阶段需要把linux学习路线搞清楚&#xff0c;任何学习都是循序渐进的&#xff0c;所以学…

从零入门机器学习之Linux系统详解

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,科大讯飞比赛第三名,CCF比赛第四名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

为什么要学习Linux?

对于一些偶然接触到Linux的人来说&#xff0c;好奇是对于这个陌生名词的的第一印象。也许这个名字经常出现在你所使用的教科书上&#xff0c;或者是一些技术性的文章上&#xff0c;你却不知其意&#xff0c;此时这个名字再次出现&#xff0c;你就更是好奇了&#xff0c;Linux到…

Linux学习总结

课程&#xff1a;Linux操作系统与应用 参考书&#xff1a;Linux从入门到精通、unix环境高级编程 学习linux之前必须要做好心理准备&#xff1a; 第一&#xff0c;要明白学好linux不是一件一蹴而就的事&#xff0c;一定要能坚持使用它&#xff0c;特别是在使用初期&#xff0c…

你知道如何学习Linux吗?

说起Linux&#xff0c;业内人士或者经常玩电脑&#xff0c;对计算机比较精通的应该是比较熟悉的&#xff0c;Linux是一个开源的操作系统&#xff0c;由于其安全性高&#xff0c;完全免费&#xff0c;高效性&#xff0c;稳定等优点&#xff0c;越来越受大众的欢迎&#xff0c;就…

学习linux的感受

学习前要 1.安装虚拟机或者自己买个云服务器 下载centOs然后将镜像装入系统 2.装入之后在自己的电脑下载Xshell和Xbox 3在自己windows系统下运行cmd拼一下自己的虚拟机或服务器测试两个机子网络是否相通&#xff0c;如果相通即可用Xshell进行远程登陆 成果: 今天学了vim与vi&…

初学者如何系统性地学习Linux?

作为一个大一的同学&#xff0c;可以采取下面的步骤进行系统的学习Linux。 1、选择一个发行版&#xff1a;对于初学者&#xff0c;推荐使用Ubuntu或者Linux Mint。Ubuntu适合新手&#xff0c;使用广泛&#xff0c;社区活跃&#xff0c;遇到问题容易找到解决方案。虽然你觉得Ub…