本篇博客是根据b站尚硅谷的数据结构教程,学习后写的学习笔记,本篇博客的重点在自己编写的代码注释和过程分析上
https://www.bilibili.com/video/BV1E4411H73v?p=98

前序遍历,中序遍历,后序遍历

首先定义节点类,这里依旧是在拿梁山好汉作为节点里面的信息

//先创建HeroNode节点
class HeroNode {private int no;private String name;private HeroNode left;  //默认为nullprivate HeroNode right; //默认为nullpublic HeroNode(int no,String name){this.no = no;this.name = name;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public String getName() {return name;}public void setName(String name) {this.name = name;}public HeroNode getLeft() {return left;}public void setLeft(HeroNode left) {this.left = left;}public HeroNode getRight() {return right;}public void setRight(HeroNode right) {this.right = right;}@Overridepublic String toString() {return "HeroNode{" +"no=" + no +", name='" + name + '\'' +'}';}//编写前序遍历的方法public void preOrder(){System.out.println(this); //打印当前根节点,每棵子树根左右的根//递归向左子树前序遍历,每棵子树根左右的左if(this.left != null){//打印当前根节点后,遍历根节点的左子树,如果左子树不为空,则对左子树执行preOrder()//this和this.left都是指向一个节点对象,因此可以调用preOrder方法//打印了左子树的根节点后,如果还能继续往左子树遍历,则一直遍历下去,直到某个根节点的左子树为空this.left.preOrder();}//递归向右子树前序遍历,每棵子树根左右的右if(this.right != null){//左子树为空后,根据前序遍历根左右的顺序,开始遍历当前根节点的右子树//对右子树的根节点运用preOrder方法,如果当前根节点有左子树,一样会再次遍历左子树this.right.preOrder();}}//遍历中序遍历的方法public void infixOrder(){//遍历左子树递归调用if(this.left != null){this.left.infixOrder();}//打印根节点System.out.println(this);//遍历右子树if(this.right != null){this.right.infixOrder();}}//遍历后序遍历的方法public void postOrder(){if(this.left != null){this.left.postOrder();}if(this.right != null){this.right.postOrder();}System.out.println(this);}}

然后定义二叉树的类

//定义BinaryTree 二叉树
class BinaryTree {//定义根节点private HeroNode root;public void setRoot(HeroNode root){this.root = root;}//前序遍历public void preOrder(){if(this.root != null){this.root.preOrder();}else{System.out.println("二叉树为空,无法遍历");}}//中序遍历public void infixOrder(){if(this.root != null){//这里的两个infixOrder()不一样,上面的infixOrder()是二叉树的方法//下面的infixOrder()是根节点在调用自己的类里面的方法this.root.infixOrder();}else{System.out.println("二叉树为空,无法遍历");}}//后序遍历public void postOrder(){if(this.root != null){this.root.postOrder();}else{System.out.println("二叉树为空,无法遍历");}}
}

编写main方法里面的代码,测试一下二叉树的前序遍历,中序遍历,后序遍历

 public static void main(String[] args) {//先创建一棵二叉树BinaryTree binaryTree = new BinaryTree();//创建需要的节点HeroNode root = new HeroNode(1,"宋江");HeroNode node2 = new HeroNode(2,"吴用");HeroNode node3 = new HeroNode(3,"卢俊义");HeroNode node4 = new HeroNode(4,"林冲");//手动将节点放入二叉树中root.setLeft(node2);root.setRight(node3);node3.setRight(node4);binaryTree.setRoot(root);//测试System.out.println("前序遍历");binaryTree.preOrder();System.out.println("中序遍历");binaryTree.infixOrder();System.out.println("后序遍历");binaryTree.postOrder();}

前序查找,中序查找,后序查找

上面是按照前序,中序,后序的顺序将二叉树里面的全部节点都输出打印出来
这里是在整个二叉树中找到一个指定的节点

首先在节点类里面新增三个方法

//前序查找:前序遍历查找一个指定的节点//如果找到就返回该Node,如果没有找到就返回nullpublic HeroNode preOrderSearch(int no){//比较当前节点是不是//前序遍历查找指定节点,先比较根节点,也就是当前节点是不是if(this.no == no){return this;}//上面如果根节点是要找的节点,则return结束方法,否则继续执行//开始判断当前节点的左子节点是否为空,如果不为空,则递归前序查找//这里定义了resNode变量,针对每个节点都会执行一次这个方法preOrdersearch()//如果当前节点是要找的节点,那么一开始的if(this.no==no)就会返回this,也就是这个节点对象,返回的对象会被resNode接收//但是如果没有找到,直到遍历左子树为null都没有找到,那么resNode依旧为nullHeroNode resNode = null;if(this.left != null){resNode = this.left.preOrderSearch(no);}if(resNode != null){return resNode;}//到这里说明左递归前序遍历没有找到节点信息,也就是根左右的根左都没有找到,开始遍历右子树if(this.right != null){resNode = this.right.preOrderSearch(no);}//遍历右子树,如果找到则返回节点,如果没有找到则返回的还是nullreturn resNode;}//中序查找:中序遍历查找一个指定节点public HeroNode infixOrderSearch(int no){//判断当前节点的左子节点是否为空,如果不为空,则递归中序查找HeroNode resNode = null;if(this.left != null){resNode = this.left.infixOrderSearch(no);}if(resNode != null){return resNode;}//比较当前节点的编号no是否是要查找的noif(this.no == no){return this;}//当前节点不是,则继续遍历当前节点的右子节点if(this.right != null){resNode = this.right.infixOrderSearch(no);}return resNode;}//后序查找:后序遍历查找某个指定节点public HeroNode postOrderSearch(int no){//判断当前节点的左子节点是否为空,如果不为空,则递归后续查找HeroNode resNode = null;if(this.left != null){resNode = this.left.infixOrderSearch(no);}if(resNode != null){return resNode;}if(this.right != null){resNode = this.right.infixOrderSearch(no);}if(resNode != null){return resNode;}//如果左右子树都没有找到,就比较当前节点是不是if(this.no == no){return this;}return resNode;}

这里其实还是分别按照前序,中序,后序的顺序遍历整个二叉树,不过是将每遍历一个节点就打印一个节点,变成了每遍历一个节点,就将当前节点的编号no与需要查找节点的编号no进行比较,如果相等说明查找成功,返回这个节点对象。如果按照前序,中序,后序的顺序遍历了整棵二叉树都没有找到编号no相等的节点,则返回null,说明当前二叉树内没有找到需要查找的节点。

方法的具体实现,无论是前序,中序,后序遍历,都一定会遍历二叉树中的每一个节点。所以三个方法其实都是拿当前遍历到的节点与要查找的节点进行比较,如果比较失败,说明当前节点不是要查找节点,则前序遍历的根左右,则继续往当前节点的左子树遍历;根据中序遍历的左根右,则继续往右子树遍历;根据后序遍历的左右根,左子树为null,右子树为null,根节点比较失败,返回null,则当前递归方法返回null,回到上一个调用此递归方法的节点。


就拿后序遍历来举例子,后序遍历一开始从根节点开始,然后

 if(this.left != null){resNode = this.left.postOrderSearch(no);}

就会一直往左子树遍历,这里没有发生节点的比较,一直遍历到左子树为空为止。也就是来到了【吴用】这个节点,也就是当前的this节点,此时this.left为null,不满足 if 判断,程序开始继续往下执行。

if(resNode != null){return resNode;}

由于此时还没有比较,一开始定义了HeroNode resNode = null;,所以这里的resNode还是null,不满足 if 判断条件,程序继续往下走

if(this.right != null){resNode = this.right.postOrderSearch(no);}if(resNode != null){return resNode;}

这里同理,这两个 if 判断条件也不符合,同样不会执行,跳过,继续往下

if(this.no == no){return this;
}

直到来到了这里,终于开始比较当前节点的编号no是否是要找的编号no了,如果是的,那么返回当前this节点,也就是【吴用】;如果不是,那么最后一句 return resNode; 返回的依旧是null

到了这里当前的postOrderSearch()方法执行结束,回到调用这个方法的地方,也就是【宋江】这个节点。这个节点一开始就因为

if(this.left != null){resNode = this.left.postOrderSearch(no);
}

往左子树遍历,this.left.postOrderSearch方法,让左子节点,也就是【吴用】调用方法,当前this节点从【宋江】变成了【吴用】。然后在【宋江】这个节点,程序继续往下执行

if(resNode != null){return resNode;
}

前面说过【吴用】节点返回的是null,不满足这里的 if 判断,跳过,不会执行里面的return语句导致方法结束

if(this.right != null){resNode = this.right.infixOrderSearch(no);
}
if(resNode != null){return resNode;
}

这里开始遍历【宋江】的右子树,遍历完成后,获取右子树的遍历结果,如果返回的值不是null,而是一个节点对象,满足第二个 if 判断里面 resNode != null 的条件,执行里面的 return resNode; 语句,结束当前方法。由于【宋江】就是根节点,因此整个postOrderSearch() 方法调用结束,返回这个节点对象。

但是如果遍历右子树后,返回的结果还是null,那么程序继续往下执行

if(this.no == no){return this;
}
return resNode;

比较【宋江】的编号no是否是要查找的编号no,如果不是,则整个方法结束,返回null,说明当前二叉树内没有要查找的编号no。如果比较成功,则将【宋江】节点对象作为整个方法查找后最后一次返回的对象。

在二叉树的类里面,同样添加前序查找,中序查找,后序查找的方法

//前序查找public HeroNode preOrderSearch(int no){if(root != null){return root.preOrderSearch(no);}else{return null;}}//中序查找public HeroNode infixOrderSearch(int no){if(root != null){return root.infixOrderSearch(no);}else{return null;}}//后序查找public HeroNode postOrderSearch(int no){if(root != null){return root.postOrderSearch(no);}else{return null;}}

在main方法里面编写测试语句

//测试,查找指定元素System.out.println("前序查找");HeroNode resNode1 = binaryTree.preOrderSearch(3);if(resNode1 != null){System.out.printf("找到了,信息为no=%d name=%s",resNode1.getNo(),resNode1.getName());}else{System.out.printf("没有找到no=%d的英雄",3);}System.out.println();System.out.println("中序查找");HeroNode resNode2 = binaryTree.infixOrderSearch(2);if(resNode2 != null){System.out.printf("找到了,信息为no=%d name=%s",resNode2.getNo(),resNode2.getName());}else{System.out.printf("没有找到no=%d的英雄",2);}System.out.println();System.out.println("后序查找");HeroNode resNode3 = binaryTree.postOrderSearch(4);if(resNode3 != null){System.out.printf("找到了,信息为no=%d name=%s",resNode3.getNo(),resNode3.getName());}else{System.out.printf("没有找到no=%d的英雄",4);}

数据结构笔记 —— 二叉树(前序、中序、后序遍历和查找)相关推荐

  1. 数据结构 5-3-2 二叉树前序中序后序遍历非递归实现

    一.前言 上一篇整理了几种遍历方式的递归实现,递归的实现方法都很简单,区区几句代码就可以实现,但是如果要用非递归的方法来实现就有些挑战了. 二.中序遍历 从中序遍历开始,其实非递归的方法就是把递归变成 ...

  2. 数据结构 - 顺序存储二叉树(前序中序后序遍历)

    就是逻辑上是二叉树,物理上是一个数组 需求 package tree;public class ArrayBinaryTreeDemo {public static void main(String[ ...

  3. c++ 删除二叉树的子树_数据结构—树|二叉树|前序遍历、中序遍历、后序遍历【图解实现】...

    点击蓝字关注我们 AI研习图书馆,发现不一样的精彩世界 数据 结构 二叉树的遍历 一.树 在谈二叉树的知识点之前,我们首先来看一下树和图的基本概念.树:不包含回路的连通无向图,树是一种简单的非线性结构 ...

  4. 【二叉树Java】二叉树遍历前序中序后序遍历的非递归写法

    本文主要介绍二叉树前序中序后序遍历的非递归写法 在探讨如何写出二叉树的前序中序后序遍历代码之前,我们先来明确一个问题,前序中序后序遍历根据什么区分? 二叉树的前序中序后序遍历,是相较根节点说的.最先遍 ...

  5. 二叉树中前序 中序 后序的互推

    最近开始复习数据结构,就从二叉树开始吧 1.复习前序 中序 后序 结构: 前序:根(左子树)(右子树) 中序:(左子树)根 (右子树) 后序:(左子树)(右子树)根 2. 前序+中序->后序 由 ...

  6. 用前序中序创建二叉树(用中序后序创建二叉树)

    定义二叉树结点 比如就拿这个二叉树 前序中序创建 因为前序遍历的顺序是 根 , 左 ,右. 中序的遍历是 左 根 右. 我们会很不好想,但我们可以用前序和中序把上面那个二叉树的遍历一边 前序遍历:AB ...

  7. 二叉树前序中序,后序中序,公共最近祖先的实现

    二叉树前序中序,后序中序,公共最近祖先的实现 注释中详细介绍了算法,故不再赘述. 无论是前序还是后序,一个节点的左子树和右子树都是可以看做是分开的,有一定规律可循,故可用递归进行实现. #includ ...

  8. 二叉树的深度(前序 中序 后序 递归非递归搜素)、广度、搜索 C++

    a b c 使用 1 2 3 表示 /* 描述:二叉树的深度(前序 中序 后序 递归非递归搜素).广度.搜索 作者:jz 日期:20140819 */ #include<stdio.h> ...

  9. 前序中序、中序后序以及前序后序构造二叉树

    文章目录 前序中序 中序后序 前序后序 定义的树节点如下, class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { ...

  10. 序列化和反序列化二叉树 -----前序,中序,后序,层序

    目录 一.序列化和反序列化 1.什么是序列化和反序列化 二.前序遍历 1.序列化 1.问题分析 2.代码实现 2.反序列化 1.问题分析 2.代码实现 三.后序遍历 1.序列化 1.思路分析 2.代码 ...

最新文章

  1. Python数据类型 - set 集合
  2. SAP中国际贸易条款的含义
  3. linux怎么用两个进程传值,关于linux:将变量脚本参数传递给另一个脚本,然后将qsub传递给程序...
  4. 阿里云ECS服务器多种实例规格如何选择
  5. 如果你是IT技术人员,请思考这15个问题
  6. Dragonfly成为CNCF孵化项目,我们与基金会首位华人TOC聊了聊
  7. 类库、框架、模块、组件等概念介绍
  8. DNA 测序技术的发展:第三代测序法
  9. 汽车控制器CAN通信DBC文件工具:EXCEL生成DBC和生成代码
  10. JAVA实现贪吃蛇游戏
  11. 怎么戒网瘾?一个玩了上百款游戏的程序员告诉你有多少废话
  12. Python实现ABC人工蜂群优化算法优化支持向量机回归模型(SVR算法)项目实战
  13. u-boot中nand相关命令使用---- ubi, ubifsls, ubifsmount, ubifsumount
  14. jquery触发键盘按下事件
  15. Java 后端开发常用的第三方服务 TOP10
  16. DDR Layout使用技巧
  17. Python数据分析_电商数据分析报告
  18. 【分享】SDLPAL 仙剑奇侠传开源项目编译
  19. 测试攻击机伪装成目标机 IP 给目标机发送攻击报文是否成功
  20. 3dmax和python哪个好学_C4D和3DMAX哪个好?

热门文章

  1. SCV work work
  2. PHP 简单案例[4]
  3. Matlab实现复化求积公式(梯形)
  4. android视频动态壁纸app,视频动态壁纸app下载-视频动态壁纸app安卓版下载V1.0安卓版 - 非凡软件站...
  5. 我是怎么找到电子书的
  6. Excel:第十一天求和函数(Sum函数)
  7. 如何输入版权特殊字符©
  8. PID控制算法的C语言实现六 抗积分饱和的PID控制算法C语言实现
  9. mac备份_备份Mac的最佳方法
  10. 观《一个也不能少》后感