算法-二叉树-简单-二叉树的遍历

记录一下算法题的学习6

首先我们要回忆一下怎么样遍历一个树:

三种遍历概念

  • 先序遍历:先访问根节点,再访问左子树,最后访问右子树。
  • 后序遍历:先左子树,再右子树,最后根节点。
  • 中序遍历:先左子树,再根节点,最后右子树。
  • 每一个子树遍历时依然按照此时的遍历顺序。

leetCode算法简单题目:

题目:给定一个二叉树的根节点 root ,返回 它的 中序 遍历 

代码与思路分析:

真香递归代码展示:
/***二叉树的中序遍历 先左子树,再根节点,最后右子树。*/
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> tree = new ArrayList<Integer>();inorder(root, tree);return tree;}public void inorder(TreeNode root, List<Integer> tree) {if (root == null) {return;}//中序遍历 定义 inorder(root) 表示当前遍历到 root\textit{root}root 节点//inorder(root.left) 来遍历 root 节点的左子树inorder(root.left, tree);//然后将root 节点的值加入答案tree.add(root.val);//inorder(root.right) 来遍历 root 节点的右子树inorder(root.right, tree);}}
 栈与迭代代码展示:

这里我们要了解栈的特点:先进后出,后进先出

  •  先序遍历,出栈顺序:根左右; 入栈顺序:右左根
  •  中序遍历,出栈顺序:左根右; 入栈顺序:右根左
  •  后序遍历,出栈顺序:左右根; 入栈顺序:根右左
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> tree = new ArrayList<Integer>(); //定义一个遍历后的二叉树列表Deque<TreeNode> stack = new LinkedList<TreeNode>();//定义栈//root为空并且stack为空,遍历就会结束while (root != null || !stack.isEmpty()) {// 满足上面条件 ,先根后左入栈while (root != null) {stack.addFirst(root); //addFirst(e)等价于 push(e),root = root.left;}//这里仔细分析// 如果这里root==null,说明上一步的root没有左子树// 1. 执行左出栈。因为此时root==null,导致root.right一定为null(左子树里的右,可能有点混,仔细想想)// 2. 执行下一次外层while代码块,根出栈。此时root.right可能存在(这里是根节点的右子树)// 3a. 若root.right存在,右入栈,再出栈// 3b. 若root.right不存在,重复步骤2执行下一次外层while代码块,即root为空并且stack为空,遍历就会结束root = stack.removeFirst(); //1.removeFirst()等价于pop()tree.add(root.val);//左子树遍历完,直接将根节点添加上去root = root.right; //然后右子树}return tree;}}

这里我事先并不知道Deque是什么,查了一下资料,在这里简单做个记录:

Deque是一个双端队列接口,继承自Queue接口,Deque的实现类是LinkedList、ArrayDeque、LinkedBlockingDeque,其中LinkedList是最常用的。

它有三种用途:a.普通队列(一端进一端出),b.双端队列(两端都可以进出),

c.堆栈Deque deque = new LinkedList()

我们在这里使用的就是堆栈,Deque堆栈操作方法:push()、pop()、peek()。下面代码会用到。

双端队列用作 LIFO(后进先出)堆栈。应优先使用此Deque接口而不是遗留 Stack 类。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。

堆栈方法完全等效于Deque 方法

堆栈方法等效Deque方法
push(e)addFirst(e)
pop()removeFirst()
peek()peekFirst()

这里展示二叉树的前序遍历:

class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> tree  = new ArrayList<Integer>();Deque<TreeNode> stack = new LinkedList<TreeNode>();if (root == null) {return tree;}while (!stack.isEmpty() || root != null) {while (root != null) {tree.add(root.val);stack.addFirst(root);root = root.left;}root = stack.removeFirst();root = root.right;}return tree;}}

这里展示二叉树的后序遍历(提示:这是我看到的leedcode中对官方代码最清晰的解释):

class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> tree = new ArrayList<Integer>();Deque<TreeNode> stack = new LinkedList<TreeNode>();if (root == null) {return tree;}//在后序遍历中,我们使用一个prev来记录历史访问记录//回溯到父节点时,可以由此来判断,上一个访问的节点是否为右子树TreeNode prev = null;while (root != null || !stack.isEmpty()) {while (root != null) {stack.push(root);root = root.left;}//从栈中弹出左子树‘先进后出’ 左子树访问完毕root = stack.pop();//现在要确定的是是否有右子树,或者右子树是否访问过//如果没有右子树,或者右子树访问完了,也就是上一个访问的节点是右子节点时//说明可以访问当前节点if (root.right == null || root.right == prev) {tree.add(root.val);//更新历史访问记录,这样回溯的时候父节点可以由此判断右子树是否访问完成prev = root;root = null;} else {//如果右子树没有被访问,那么将当前节点压栈,访问右子树stack.push(root);root = root.right;}}return tree;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/191588.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DEEP-FRI: Sampling Outside the Box Improves Soundness论文学习笔记

1. 引言 前序博客有&#xff1a; DEEP FRI协议A summary on the FRI low degree test前2页导读RISC Zero的手撕STARKReed-Solomon Codes——RS纠错码Reed-Solomon Codes及其与RISC Zero zkVM的关系 Eli Ben-Sasson等人2019年论文《DEEP-FRI: Sampling Outside the Box Impro…

从键盘输入5个学生的信息(姓名、学号、成绩), 存入一个结构体数组中,计算平均分,并按成绩 高低排序并输出.

代码如下 #include<stdio.h> #include<string.h> #include<stdlib.h> /* 1.练习结构体数组排序   从键盘输入5个学生的信息&#xff08;姓名、学号、成绩&#xff09;,存入一个结构体数组中&#xff0c;计算平均分&#xff0c;并按成绩高低排序并输出. */…

harmonyOS鸿蒙开发工具下载安装以及使用流程

注册账号 进入鸿蒙官方网站&#xff1a;https://www.harmonyos.com/ 推荐使用手机号注册 进行实名认证 下载开发环境 华为集成开发环境IDE DevEco Device Tool下载 | HarmonyOS设备开发 下载开发工具 HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 安装 无脑下一…

车载开发岗位如何?Android程序员是否转行

这几年的大环境让大家都过的不安逸&#xff1b;社会动荡与就业问题一直困扰了不少人。在大家都认为的高薪工作程序员行业中&#xff0c;现在也是费力不讨好裁员风潮大部分指向互联网。 我们Android开发基本上已经感受很久了&#xff0c;就这就业问题很难存活。对此我们的目光都…

【MySQL学习笔记-001】- 创建表、插入数据、查看数据库结构

创建employees表 当创建一个表时&#xff0c;需要指定表的名称和每个列的名称和数据类型。以下是一个示例SQL语句&#xff0c;用于创建一个名为"employees"的表&#xff0c;其中包含员工ID、姓名、职位和工资等列&#xff1a; CREATE TABLE employees (employee_id…

AI Navigation导航系统_unity基础开发教程

AI Navigation导航系统 安装插件烘焙导航系统障碍物创建人物的AI导航动态障碍物 在unity编辑器中&#xff0c;有一个灰常好用的插件&#xff1a;Navigation。有了它1&#xff0c;你就可以实现人物自动走到你鼠标点击的位置&#xff0c;而且还会自动避开障碍物&#xff0c;下面就…

java源码-工程讲解

1、 工程目录 源码工程目录讲解部分&#xff0c;讲解过程会让大家对后端源码工程有一个大致的了解&#xff0c;能让大家在此改造&#xff0c;就可以衍生出一些新的功能&#xff0c;需要对java技术深入了解&#xff0c;需要看后续java技术讲解部分 整个架构是一个spring-boot…

Canal+Kafka实现MySQL与Redis数据同步(一)

CanalKafka实现MySQL与Redis数据同步&#xff08;一&#xff09; 前言 在很多业务情况下&#xff0c;我们都会在系统中加入redis缓存做查询优化。 如果数据库数据发生更新&#xff0c;这时候就需要在业务代码中写一段同步更新redis的代码。 这种数据同步的代码跟业务代码糅合…

QUIC协议详解

前言协议特点QUIC协议与HTTP/2协议区别QUIC协议的多路复用技术优势QUIC协议在Java中的应用存在的问题 前言 QUIC&#xff08;Quick UDP Internet Connections&#xff09;是一种基于 UDP 的传输层协议&#xff0c;由 Google 提出。从协议栈可以看出&#xff0c;QUIC HTTP/2 …

最常用的结构体初始化方式

结构体最常用的初始化方式就是用memset把这块区域清0 注意不能这么写 STU stu[5]; stu (STU*)malloc(sizeof(stu)); 数组名不允许被赋值&#xff0c;它只是个表达式

如何使用fiddler实现手机抓包,Filters过滤器!

一、Fiddler与其他抓包工具的区别 1、Firebug虽然可以抓包&#xff0c;但是对于分析http请求的详细信息&#xff0c;不够强大。模拟http请求的功能也不够&#xff0c;且firebug常常是需要“无刷新修改”&#xff0c;如果刷新了页面&#xff0c;所有的修改都不会保存&#xff1b…

13.真刀实枪做项目---博客系统(页面设计)

文章目录 1.预期效果1.1博客列表页效果1.2博客详情页效果1.3博客登陆页效果1.4博客编辑页效果 2.实现博客列表页2.1实现导航栏2.2实现版心2.3实现个人信息2.4实现博客列表2.5博客列表页完整代码 3.实现博客正文页3.1引入导航栏3.2引入版心3.3引入个人信息3.4实现博客正文3.5博客…