遍历线索化二叉树+图解

图解

在这里插入图片描述

代码实现

package com.atguigu.tree.threadedbinarytree;/*** @创建人 wdl* @创建时间 2021/3/25* @描述*/
public class ThreadedBinaryTreeDemo {public static void main(String[] args) {//测试一把中序线索化二叉树的功能HeroNode root = new HeroNode(1, "tom");HeroNode node2 = new HeroNode(3, "jack");HeroNode node3 = new HeroNode(6, "smith");HeroNode node4 = new HeroNode(8, "mary");HeroNode node5 = new HeroNode(10, "king");HeroNode node6 = new HeroNode(14, "dim");//二叉树,后面我们需要递归创建,现在手动创建root.setLeft(node2);root.setRight(node3);node2.setLeft(node4);node2.setRight(node5);node3.setLeft(node6);//测试中序线索化ThreadedBinaryTree threadedBinaryTree = new ThreadedBinaryTree();threadedBinaryTree.setRoot(root);threadedBinaryTree.threadedNodes();//测试:以10号节点测试HeroNode leftNode = node5.getLeft();HeroNode rightNode = node5.getRight();System.out.println("10号节点的前驱节点是"+leftNode);System.out.println("10号节点的后继节点是"+rightNode);//当线索化二叉树后System.out.println("使用线索化的方式遍历 线索化二叉树");threadedBinaryTree.threadedList();//8,3,10,1,14,6}}//定义ThreadedBinaryTree实现了线索化功能的二叉树
class ThreadedBinaryTree{private HeroNode root;//为了实现线索化,需要创建一个指向当前节点的前驱节点的指针//在递归进行线索化是,pre总是保留前一个节点private HeroNode pre=null;public void setRoot(HeroNode root){this.root=root;}//重载threadedNodes方法public void threadedNodes(){this.threadedNodes(root);}//遍历线索化二叉树的方法public void threadedList(){//定义一个变量,存储当前遍历的节点,从root开始HeroNode node=root;while (node!=null){//循环的扎到leftType==1的节点,第一个找到的就是8节点//后面会随着遍历而变化,因为当lefType==1时,说明该节点是按照线索化//处理后的有效节点while (node.getLeftType()==0){node=node.getLeft();}//打印当前的节点System.out.println(node);//如果当前节点的右指针指向的是后继节点,就一直输出while (node.getRightType()==1){//获取到当前节点的后继节点node=node.getRight();System.out.println(node);}//替换这个遍历的节点node=node.getRight();}}//编写对二叉树进行中序线索化的方法/**** @param node 就是当前需要线索化的节点*/public void threadedNodes(HeroNode node){//如果node==null,不能线索化if(node==null){return;}//1.先线索化左子树threadedNodes(node.getLeft());//2.线索化当前节点[有难度]//处理当前节点的前驱节点//以8节点来理解//8节点的.left=null,8节点的.leftType=1if(node.getLeft()==null){//当前节点的左指针指向前驱节点node.setLeft(pre);//修改当前节点的左指针的类型,指向前驱节点node.setLeftType(1);}//处理当前节点的后继节点if(pre!=null&&pre.getRight()==null){//让前驱节点的右指针指向当前节点pre.setRight(node);//修改前驱节点的右指针类型pre.setRightType(1);}//!!!每处理一个节点,让当前节点是下一个节点的前驱节点pre=node;//3.再线索化右子树threadedNodes(node.getRight());}//删除节点public void delNode(int no){if(root!=null){//如果只有一个root接地那,这里立即判断root是不是就是要删除的节点if(root.getNo()==no){root=null;}else {//递归删除root.delNode(no);}}else {System.out.println("空树,不能删除");}}//前序遍历public void preOrder(){if(this.root!=null){this.root.preOrder();}else {System.out.println("二叉树为空,无法遍历");}}//中序遍历public void infixOrder(){if(this.root!=null){this.root.infixOrder();}else {System.out.println("二叉树为空,无法遍历");}}//后序遍历public void postOrder(){if(this.root!=null){this.root.postOrder();}else {System.out.println("二叉树为空,无法遍历");}}//前序查找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;}}}//先创建HeroNode节点
class HeroNode{private int no;private String name;private HeroNode left;//默认为nullprivate HeroNode right;//默认为null//说明//1.如果leftType==0表示指向的是左子树,如果是1则表示指向前驱节点//2.如果rightType==0表示指向的是右子树,如果是1则表示指向后继节点private int leftType;private int rightType;public int getLeftType() {return leftType;}public void setLeftType(int leftType) {this.leftType = leftType;}public int getRightType() {return rightType;}public void setRightType(int rightType) {this.rightType = rightType;}public HeroNode(int no, String name) {super();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 + '\'' +'}';}//递归删除节点//1.如果删除的节点是叶子节点,则删除该节点//2.如果删除的节点是非叶子节点,则删除该子树public void delNode(int no){if(this.left!=null&&this.left.no==no){this.left=null;return;}if(this.right!=null&&this.right.no==no){this.right=null;return;}if(this.left!=null){this.left.delNode(no);}if(this.right!=null){this.right.delNode(no);}}//编写前序遍历的方法public void preOrder(){System.out.println(this);//先输出父节点//递归向左子树前序遍历if(this.left!=null){this.left.preOrder();}//递归向右子树前序遍历if(this.right!=null){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);//输出父节点}/**** @param no 查找no* @return 如果找到就返回该Node,如果没有找到返回null*///前序遍历查找public HeroNode preOrderSearch(int no){System.out.println("进入前序查找");//比较当前节点是不是if(this.no==no){return this;}//1.则判断当前节点的左子节点是否为空,如果不为空,则递归前序查找//2.如果左递归前序查找,找到节点,则返回HeroNode resNode=null;if(this.left!=null){resNode=this.left.preOrderSearch(no);}if(resNode!=null){//说明我们左子树找到return resNode;}//1.左递归前序查找,找到节点,则返回,否则判断//2.当前的节点的右子节点是否为空,如果不空,则继续向右递归前序查找if(this.right!=null){resNode=this.right.preOrderSearch(no);}return resNode;}//中序遍历查找public HeroNode infixOrderSearch(int no){//判断当前节点的左子节点是否为空,如果不为空,则递归中序查找HeroNode resNode=null;if(this.left!=null){resNode=this.left.infixOrderSearch(no);}if(resNode!=null){//说明我们左子树找到return resNode;}System.out.println("进入中序查找");//如果找到,则返回,如果没有找到,就和当前节点比较,如果是则返回当前节点if(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.postOrderSearch(no);}if(resNode!=null){//说明我们左子树找到return resNode;}//如果左子树没有找到,则向右子树递归进行后序遍历查找if(this.right!=null){resNode=this.right.postOrderSearch(no);}if(resNode!=null){//说明我们右子树找到return resNode;}System.out.println("进入后序遍历");//如果左右子树都没有找到,就比较当前节点是不是if(this.no==no){return this;}return resNode;}}

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

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

相关文章

JS实现星星评分功能实例代码(两种方法)

转载自 JS实现星星评分功能实例代码(两种方法) 一、方法1 1、用到图片 2、结构和样式 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Document</title><style>ul {padding-left: 0;…

SQL on Linux Run on Docker

摘要 SQL Server 2016以及SQL on Linux版本已经支持跑在Docker容器中&#xff0c;也展示微软拥抱开源的决心和勇气。这篇博文就是以SQL on Linux为例&#xff0c;看看如何将SQL Server实例部署在Docker容器中。 背景 大概在两个月之前&#xff0c;在SQL On Linux刚发布预览版本…

三条中线分的六个三角形_八年级数学上册:三角形已知两条边如何求第三边

三角形一、定义&#xff1a;由不在同一条直线上的三条线段首尾顺次相接所组成的平面图形叫做三角形。1、三角形的内角&#xff1a;三角形的没两条边所组成的角叫做三角形的内角2、三角形的外角&#xff1a;三角形的任意一边与另一边的反向延长线所组成的角叫做三角形的外角。二…

Xamarin的坑 - 绑定(二) - 高德iOS SDK(.Framework)绑定的一些事

编者语&#xff1a;入门总是用一个hello world&#xff0c;总会让人觉得写code会是很容易的事。开篇绑定了一下微信SDK,不会有太多的难点&#xff0c;可是接下来的这个例子如果欠缺一些耐心&#xff0c;估计你整个人就崩溃了(我从来不会放弃任何的事)。ps这里得谢谢CSDN回帖的人…

android 监听安装来源_Flutter插件开发之APK自动安装

点击上方的终端研发部&#xff0c;右上角选择“设为星标”每日早9点半&#xff0c;技术文章准时送上公众号后台回复“学习”&#xff0c;获取作者独家秘制精品资料往期文章记五月的一个Android面试经今日头条屏幕适配方案落地研究图解算法&#xff1a;说一道字节跳动的算法题除…

JavaScript学习总结(一)——JavaScript基础

转载自 JavaScript学习总结(一)——JavaScript基础 一、JavaScript语言特点 1.1、JavaScript是基于对象和事件驱动的(动态的) 它可以直接对用户或客户输入做出响应&#xff0c;无须经过Web服务程序。它对用户的响应&#xff0c;是采用以事件驱动的方式进行的。所谓事件驱动…

idea下使用springinitializr创建项目时 初始化失败的解决

idea自带的地址无使用使用阿里的就可以了 idea下使用springinitializr创建项目时 初始化失败的解决 周山 关注 2020.08.05 13:32:26字数 10阅读 1,085 image.png 修改初始化创建时Custom处 https://start.aliyun.com/ image.png

如何使Mac Docker支持SQL on Linux容器Volume特性

问题引入 这天老鸟火急火燎的找到菜鸟&#xff1a;“鸟儿啊&#xff0c;按照你之前的文章SQL on Linux Run on Docker&#xff0c;当我销毁SQL on Linux Docker容器以后&#xff0c;我容器中的所有数据库数据丢失啦&#xff0c;怎么办&#xff0c;怎么办啊&#xff1f;”。菜鸟…

JavaScript学习总结(二)——逻辑Not运算符详解

转载自 JavaScript学习总结(二)——逻辑Not运算符详解 在JavaScript 中&#xff0c;逻辑NOT运算符与C和Java中的逻辑 NOT 运算符相同&#xff0c;都由感叹号&#xff08;!&#xff09;表示。与逻辑 OR 和逻辑 AND 运算符不同的是&#xff0c;逻辑 NOT 运算符返回的一定是 Boo…

赫夫曼树+图解

图解 代码实现 package com.atguigu.huffmanTree;import javax.swing.*; import java.awt.geom.RoundRectangle2D; import java.util.ArrayList; import java.util.Collections; import java.util.List;/*** 创建人 wdl* 创建时间 2021/3/26* 描述*/ public class HuffmanTree…

四足爬行机器人运动_有自我意识机器人横空出世,还能自我复制,专家表示需警惕其失控...

有自我意识是什么样的&#xff1f;人类自身其实就是有自我意识的生命体&#xff0c;那作为有自我意识的生命体&#xff0c;你想过自我意识是指哪些特征吗&#xff1f;指尖科技说小编先跟你探讨一下&#xff1a;1.主动做事情。就是说在没有其他人控制的情况下&#xff0c;它可以…

微软AirSim,一个无人机和机器人的模拟器

微软开发并开源了AirSim&#xff0c;一个用于模拟无人机在全世界的飞行的工具。这个模拟器基于虚幻引擎&#xff08;Unreal Engine&#xff09;构建&#xff0c;微软很快会增加对机器人和其它类型移动设备的支持。 微软在内部开发了航空信息系统和机器人平台&#xff0c;这个研…

JavaScript学习总结(四)——逻辑OR运算符详解

转载自 JavaScript学习总结(四)——逻辑OR运算符详解 在JavaScript中&#xff0c;逻辑OR运算符用||表示 var bTrue true;var bFalse false;var bResult bTrue || bFalse; 下面的真值表描述了逻辑AND运算符的行为: 运算数 1运算数 2结果truetruetruetruefalsetruefals…

LEANSOFT领航员 – 基于Docker的DevOps实战培训

2016年&#xff0c;LEANSOFT推出了一系列广受开发人员欢迎的培训&#xff0c;包括《构建高效DevOps团队》&#xff0c;《基于Azure的容器化DevOps数据中心》和《Docker基础培训》。在这些培训中&#xff0c;我们得到了很多反馈&#xff0c;大家对使用Docker来支持DevOps的场景有…

高德地图路线规划 时间_路线准、播报拥堵及时,这次自驾出行高德地图可算是帮了大忙...

在我们日常生活中,自驾已经成为一种很普遍的出行方式,不仅在时间上灵活,特别是一家人出行也比较方便。伴随自驾出行的除了爱车外,一款靠谱的地图导航软件也成为了必不可少的旅行伙伴。目前比较常用的地图导航软件当属高德、百度和腾讯,不少人手机里都会有这三款软件中的其中一个…

JavaScript学习总结(七)——JavaScript函数(function)

转载自 JavaScript学习总结(七)——JavaScript函数(function) 一、函数基本概念 为完成某一功能的程序指令(语句)的集合&#xff0c;称为函数。 二、JavaScript函数的分类 1、自定义函数(我们自己编写的函数)&#xff0c;如&#xff1a;function funName(){} 2、系统函数(J…

JavaScript学习总结(八)——JavaScript数组

转载自 JavaScript学习总结(八)——JavaScript数组 JavaScript中的Array对象就是数组&#xff0c;首先是一个动态数组&#xff0c;无需预先制定大小&#xff0c;而且是一个像Java中数组、ArrayList、Hashtable等的超强综合体。 一、数组的声明 常规方式声明&#xff1a; 1、…

命令点无效怎么处理_CAD执行修改命令,你试过重复选择对象吗?

你在执行命令的时候&#xff0c;是习惯先选择对象还是之后才选择对象的呢&#xff1f;不知道细心的你有没有发觉&#xff0c;明明已经先选择对象了才执行命令&#xff0c;为什么之后还要重复选择对象&#xff1f;这里可以分几种情况来讨论一下。CAD版本&#xff1a;中望CAD 202…

一起脱去小程序的外套和内衣 - 微信小程序架构解析

作者介绍&#xff1a; 渠宏伟&#xff0c;腾讯高级工程师&#xff0c;从事Web前端开发5年&#xff0c;先后负责企鹅电竞、腾讯视频VIP、腾讯OA开发框架、腾讯微信HR助手等项目。对Web前端架构、.NET架构有丰富的经验。 | 导语 微信小程序的公测掀起了学习小程序开发的浪潮&…