Java 树结构的基础部分(二)
package com.lin.tree_0308;
public class ArrBinaryTreeDemo {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7};
ArrBinaryTree arrBinaryTree = new ArrBinaryTree(arr);
System.out.println("前序遍历:");
arrBinaryTree.preOrder();
System.out.println();
System.out.println("中序遍历:");
arrBinaryTree.infixOrder();
System.out.println();
System.out.println("后序遍历:");
arrBinaryTree.postOrder();
}
}
class ArrBinaryTree{
private int[] arr;
public ArrBinaryTree(int[] arr) {
super();
this.arr = arr;
}
// 重载
public void preOrder() {
this.preOrder(0);
}
public void infixOrder() {
this.infixOrder(0);
}
public void postOrder() {
this.postOrder(0);
}
/**
*
* @Description:
* @author LinZM
* @date 2021-3-8 19:14:45
* @version V1.8
* @param index 数组下标
*/
// 前序遍历
public void preOrder(int index) {
if(arr == null || arr.length == 0) {
System.out.println("数组为空!");
}
// 输出当前数据
System.out.print(arr[index] + " ");
// 向左递归
if( ( index * 2 + 1 ) < arr.length ) {
preOrder( index * 2 + 1 );
}
// 向右递归
if( ( index * 2 +2 ) < arr.length ) {
preOrder( index * 2 + 2 );
}
}
// 中序遍历
public void infixOrder(int index) {
if(arr == null || arr.length == 0) {
System.out.println("数组为空!");
}
// 向左递归
if( ( index * 2 + 1 ) < arr.length) {
infixOrder( index * 2 + 1);
}
// 输出当前数据
System.out.print(arr[index] + " ");
// 向右递归
if( ( index * 2 + 2 ) < arr.length) {
infixOrder(index*2 + 2);
}
}
// 后序遍历
public void postOrder(int index) {
if(arr == null || arr.length == 0) {
System.out.println("数组为空!");
}
// 向左递归
if( ( index * 2 + 1) < arr.length ) {
postOrder(index * 2 + 1);
}
// 向右递归
if( ( index * 2 + 2 ) < arr.length) {
postOrder(index * 2 + 2);
}
// 输出当前数据
System.out.print(arr[index] + " ");
}
}


package com.lin.tree_0308;
public class ThreadeBinaryTreeDemo {
public static void main(String[] args) {
TNode tNode1 = new TNode(1, "Tom");
TNode tNode2 = new TNode(3, "Jack");
TNode tNode3 = new TNode(6, "Smith");
TNode tNode4 = new TNode(8, "Marry");
TNode tNode5 = new TNode(10, "Linda");
TNode tNode6 = new TNode(14, "King");
tNode1.setLeft(tNode2);
tNode1.setRight(tNode3);
tNode2.setLeft(tNode4);
tNode2.setRight(tNode5);
tNode3.setLeft(tNode6);
TBinaryTree tBinaryTree = new TBinaryTree();
tBinaryTree.setRoot(tNode1);
tBinaryTree.threadedInfixNodes(tNode1);// 10test
TNode left = tNode5.getLeft();
TNode right = tNode5.getRight();
System.out.println(left);
System.out.println(right);
// // 中序遍历线索化二叉树
// System.out.println("中序遍历线索化二叉树:");
// tBinaryTree.threadedInfixList();
}
}
class TBinaryTree{
private TNode root;
// 前驱节点的指针,总是保留前一个节点
private TNode pre;
public void setRoot(TNode root) {
this.root = root;
}
public void threadedPreNodes(TNode node) {
if(node == null) {
System.out.println("空!!!");
return;
}
// 1 线索当前节点
// 先处理节点的前驱节点
if (node.getLeft() == null) {
// 让当前节点的左指针指向前驱节点
node.setLeft(pre);
// 修改当前节点的左指针的类型
node.setLeftType(1);
}
// 处理后继节点
if (pre != null && pre.getRight() == null) {
pre.setRight(node);
pre.setRigthType(1);
}
// 每处理一个节点后,让当前节点是下一个节点前驱节点
pre = node;
threadedPreNodes(node.getLeft());
threadedPreNodes(node.getRight());
}
// 二叉树中序线索化
/**
*
* @Description:
* @author LinZM
* @date 2021-3-8 22:14:51
* @version V1.8
* @param node 线索化节点
*/
public void threadedInfixNodes(TNode node) {
if(node == null) {
return;
}
// 1 先线索化左子树
threadedInfixNodes(node.getLeft());
// 2 线索化当前节点
// 先处理节点的前驱节点
// 节点8->节点3,一开始8为node,后面3为node
if(node.getLeft() == null ) {
// 让当前节点的左指针指向前驱节点
node.setLeft(pre);
// 修改当前节点的左指针的类型
node.setLeftType(1);
}
// 处理后继节点
if(pre != null && pre.getRight() == null) {
pre.setRight(node);
pre.setRigthType(1);
}
// 每处理一个节点后,让当前节点是下一个节点前驱节点
// pre = 8
pre = node;
// 3 线索化右子树
threadedInfixNodes(node.getRight());
}
// 中序遍历线索二叉树
public void threadedInfixList() {
// 定义一个变量,存储当前遍历的节点,从root开始
TNode node = root;
if(node == null) {
System.out.println("空树!");
return;
}
while(node != null) {
// 循环找到leftType == 1 的节点,第一个找到就是8节点
// 后面随着遍历而变化,因为当leftType == 1,说明该节点是按照线索化处理后的有效节点
while(node.getLeftType() == 0) {
node = node.getLeft();
}
// 找到8节点
System.out.println(node);
// 如果当前节点的右指针指向的是后继节点,就一直输出
while(node.getRigthType() == 1) {
node = node.getRight();
System.out.println(node);
}
// 如果不是后继节点,则替换这个遍历的节点
node = node.getRight();
}
}
// 删除节点
public void delNode(int no) {
if (root != null) {
// 如果只有一个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 TNode preOrderSearch(int no) {
if(root != null) {
return root.preOrderSearch(no);
} else {
return null;
}
}
// 中序查找
public TNode infixOrderSearch(int no) {
if (root != null) {
return root.infixOrderSearch(no);
} else {
return null;
}
}
// 后序查找
public TNode postOrderSearch(int no) {
if (root != null) {
return root.postOrderSearch(no);
} else {
return null;
}
}
}
class TNode{
private String name;
private int no;
private TNode left;
private TNode right;
// leftType == 0 为左子树, 如果为1则表示指向前驱节点
// rightType == 0 为右子树, 如果为1则表示指向后继节点
private int leftType;
private int rigthType;
public int getLeftType() {
return leftType;
}
public void setLeftType(int leftType) {
this.leftType = leftType;
}
public int getRigthType() {
return rigthType;
}
public void setRigthType(int rigthType) {
this.rigthType = rigthType;
}
public TNode(int no, String name) {
this.no = no;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public TNode getLeft() {
return left;
}
public void setLeft(TNode left) {
this.left = left;
}
public TNode getRight() {
return right;
}
public void setRight(TNode right) {
this.right = right;
}
@Override
public String toString() {
return "TNode [name=" + name + ", no=" + 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); // 输出父节点
}
// 前序查找
public TNode preOrderSearch(int no) {
System.out.println("1");
// 比较当前节点是不是
if(this.no == no) {
return this;
}
// 1 判断当前节点的左节点是否为空,如果不为空,则递归前序查找
// 2 如果左递归前序查找,找到节点,则返回
TNode 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);
}
// 这时候不管有没有找到都要返回resNode
return resNode;
}
// 中序查找
public TNode infixOrderSearch(int no) {
TNode resNode = null;
if(this.left != null) {
resNode = this.left.infixOrderSearch(no);
}
if(resNode != null) {
return resNode;
}
System.out.println("1");
if(this.no == no) {
return this;
}
if(this.right != null) {
resNode = this.right.infixOrderSearch(no);
}
return resNode;
}
// 后序查找
public TNode postOrderSearch(int no) {
TNode 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("1");
if(this.no == no) {
return this;
}
// 如果都没有找到
return resNode;
}
/**
*
* @Description:1 因为我们的二叉树是单向,所以我们是判断当前节点的子节点是否需要删除节点,而不是直接去判断当前节点是否需要删除节点。<br>
* 2 如果当前节点的左子节点不为空,并且左子节点就是要删除节点,就将this.left = null;并且就返回(结束递归删除) <br>
* 3 如果当前节点的右子节点不为空,并且右子节点就是要删除节点,就将this.right = null;并且就返回(结束递归删除) <br>
* 4 如果第2和第3都没有删除节点,那么我们就需要向左子树进行递归删除<br>
* 5 如果第4补也没有删除节点,则向右子树进行递归删除<br>
* @author LinZM
* @date 2021-3-8 15:17:32
* @version V1.8
*/
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);
}
}
}
仅供参考,有错误还请指出!
有什么想法,评论区留言,互相指教指教。
觉得不错的可以点一下右边的推荐哟
Java 树结构的基础部分(二)的更多相关文章
- JVM 内部原理(七)— Java 字节码基础之二
JVM 内部原理(七)- Java 字节码基础之二 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...
- java接口自动化基础知识(二)
二.HttpClient+testNG实现对接口的测试及校验 在上面第一篇中已经实现了基础配置和测试用例数据准备,本篇文章将以登录举例进行测试执行. 这是之前login接口的代码 @Test(grou ...
- JAVA之Mybatis基础入门二 -- 新增、更新、删除
上一节说了Mybatis的框架搭建和简单查询,这次我们来说一说用Mybatis进行基本的增删改操作: 一. 插入一条数据 1.首先编写USER.XML(表的xml)使用insert元素,元素写在map ...
- Java面试题-基础篇二(干货)
11.是否可以从一个static方法内部发出对非static方法的调用? 不可以.因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用 ...
- 第2章 Java并行程序基础(二)
2.3 volatile 与 Java 内存模型(JMM) volatile对于保证操作的原子性是由非常大的帮助的(可见性).但是需要注意的是,volatile并不能代替锁,它也无法保证一些复合操作的 ...
- Java 树结构的基础部分(一)
二叉树 1.1 为什么需要树这种数据结构 1) 数组存储方式的分析 优点:通过下标方式访问元素,速度快.对于有序数组,还可使用二分查找提高检索速度. 缺点:如果要检索具体某个值,或者插入值(按一定顺序 ...
- Java语言基础(二) Java关键字
Java语言基础(二) Java关键字 Java关键字比较多,我就不列举出来了,只记录一些常用的小知识点: ①Java的关键字只有小写. ②then.sizeof都不是Java的关键字,熟悉C++的程 ...
- Java语言基础(二)
Java语言基础(二) 一.变量续 (1).变量有明确的类型 (2).变量必须有声明,初始化以后才能使用 (3).变量有作用域,离开作用域后自动回收 变量作用域在块内有效 (4).在同一定义域中变量不 ...
- java 基础知识二 基本类型与运算符
java 基础知识二 基本类型与运算符 1.标识符 定义:为类.方法.变量起的名称 由大小写字母.数字.下划线(_)和美元符号($)组成,同时不能以数字开头 2.关键字 java语言保留特殊含义或者 ...
随机推荐
- SOHO 程序员
SOHO 程序员:从事程序开发.维护的家居办公人员. 一.自由程序员 SOHO程序员代表一种自由.弹性而新型的工作方式.SOHO,代表一种新经济.新概念. 是一些热爱软件开发的一族. SOHO程序员 ...
- spring再学习之AOP事务
spring中的事务 spring怎么操作事务的: 事务的转播行为: 事务代码转账操作如下: 接口: public interface AccountDao { //加钱 void addMoney( ...
- C语言经典面试题
[题目]零值比较--BOOL,int,float,指针变量与零值比较的if语句. (首先给个提示:题目中要求的是零值比较,而非与0进行比较,在C++里"零值"的范围可就大了,可以是 ...
- Linux 驱动框架---dm9000分析
前面学习了下Linux下的网络设备驱动程序的框架inux 驱动框架---net驱动框架,感觉知道了一个机器的大致结构还是不太清楚具体的细节处是怎么处理的,所以今天就来以dm9000这个网上教程最多的驱 ...
- zsh terminal set infinity scroll height
zsh terminal set infinity scroll height zsh Terminal 开启无限滚动 https://stackoverflow.com/questions/2761 ...
- CSS3 & Grid Layout All In One
CSS3 & Grid Layout All In One W3C https://www.w3.org/TR/css-grid-1/ Grid Layout is a new layout ...
- React Native Apps
React Native Apps https://github.com/ReactNativeNews/React-Native-Apps github app https://github.com ...
- 人物传记——Kyle Tedford:持之以恒的品质从哪里来?
心理学家表示,95%的人类行为发生在无意识中,而大多数这种行为是由习惯引起的.习惯,就像我们大脑设定的程序.通过每日持续努力,你会把坚持的习惯节奏慢慢进入身体中,并且会很容易加持下去. 做事三分钟热度 ...
- 直播预告 | 全面的审计分析和权限管控——CloudQuery年终发布!
2020年9月,CloudQuery 发布. 针对开发.运维人员面临的如何高效便捷访问.操作管理数据的问题,我们设计并研发了云原生安全数据操作平台,CloudQuery 就此诞生! 2020年结束之际 ...
- Unity安卓apk打包过程
前言:对于Unity开发小白来说,Android打包无疑是个头痛的问题,所以我总结了 Unity安卓APK的打包过程 第一步:下载对应版本的Android Platform 第二步:安装JDK并配置J ...