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语言保留特殊含义或者 ...
随机推荐
- 踏上Revit二次开发之路 0 序
0 序 近来,由于工作上的需要,开始自学Revit二次开发. Revit由欧特克公司专为BIM构建,是建筑业体系中使用最广泛的软件之一.借助欧特克公司在我国市场占有率方面的绝对优势,甚至给不少人带来& ...
- 在Blazor Server 项目中使用 EF Core Sqlite
按照教程创建了一个 Blazor Server 项目 教程地址: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/build-a-blaz ...
- Docker运行时资源限制
Docker 运行时资源限制Docker 基于 Linux 内核提供的 cgroups 功能,可以限制容器在运行时使用到的资源,比如内存.CPU.块 I/O.网络等. 内存限制概述Docker 提供的 ...
- ArcGIS处理栅格数据(二)
五.栅格数据的配准 1.有参考图层 ① 在ArcMap里面添加需要配准的栅格数据集和参考数据集. ② 在ArcMap里面添加"地理配准"工具条. 添加成功后如下图所示: ③ 将需要 ...
- 4.Direct交换机之使用指定routingkey完成日志记录场景
标题 : 4.Direct交换机之使用指定routingkey完成日志记录场景 目录 : RabbitMQ 序号 : 4 const string logOthersQueueName = " ...
- 牛年 dotnet云原生技术趋势
首先祝大家:新年快乐,牛年大吉,牛年发发发! 2020年的春节,新冠疫情使得全球业务停滞不前,那时候,没有人知道会发生什么,因此会议被取消,合同被搁置,项目被推迟,一切似乎都停止了.但是我们却见证了I ...
- leetcode15 三数之和 双指针
注意题目没要求数字只能用一次 a + b + c = 0 即为 -b=a+c,同时要求数字不全为正(然后发现a+b+c就行...不过多想想没坏处嘛) 先处理特殊情况,然后 先排序 注意不重复,只需要有 ...
- codeforces 6E (非原创)
E. Exposition time limit per test 1.5 seconds memory limit per test 64 megabytes input standard inpu ...
- springboot使用RestTemplate+httpclient连接池发送http消息
简介 RestTemplate是spring支持的一个请求http rest服务的模板对象,性质上有点像jdbcTemplate RestTemplate底层还是使用的httpclient(org.a ...
- 浅谈WEB前端规范化标准之ESlint
规范化标准 软件开发需要多人开发,不同的开发者具有不同的编码习惯和喜好,不同的喜好增加项目的维护成本,所以需要明确统一的标准,决定 了项目的可维护性,人为的约定不可靠,所以需要专门的工具进行约束,并且 ...