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语言保留特殊含义或者 ...
随机推荐
- docker的底层-隔离的核心
在了解底层原理之前: 说几个名词: 解耦状态: 所有东西都没有重复,任何东西都没有公用的地方. 半解耦状态:有部分共同的一起用,其他的独立 完全解耦状态: 就是各自都是独立没有重复. kvm:完全解耦 ...
- C# wpf window
使用vs2017 新建wpf 项目 MainWindow 被定义为partial,是因为他要和xaml的一些属性组合在一起,然后再运行起来,这正是 InitailizeCompoent 这个函数要干的 ...
- 快速计算类似斐波那契数列数列的数列的第N项,矩阵快速幂
这个题有循环节,可以不用这么做,这个可以当一个模板 #include <iostream> #include <cstdio> using namespace std; typ ...
- Ubuntu pppoeconf失败
之前是通过sudo pppoeconf一路yes就可以连通有线网络(dsl和ethernet)的, 系统再次瘫痪后终于进入图形界面, 有线网络丢失, sudo pppoeconf也fail了, 其实加 ...
- MobX All In One
MobX All In One Simple, scalable state management. https://mobx.js.org/README.html https://github.co ...
- js & h5 & app & object storage
js & h5 & app & object storage API https://developer.mozilla.org/en-US/docs/Web/API Stor ...
- PWA & bug
PWA bug https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps https://learning.xgqfrms.x ...
- 详解稳定币圣杯USDN
稳定币飞速发展,USDN 一骑绝尘,但因合规问题饱受质疑.合规稳定币作为后来者,奋起直追,亦光耀夺目.而更符合区块链精神的稳定币(抵押其他资产生成稳定币),长期以来只有 Maker 的 DAI 能够在 ...
- go-admin在线开发平台学习-3[细节解析]
本章节主要的内容是对go-admin中的一些有趣编码进行分析,为自己以后提供一些借鉴 使用cli方式启动项目 使用cobra[眼镜蛇]完成强壮cli的工具,确保稳定. 使用cli的方式启动项目的好处显 ...
- django学习-18.*args和**kwargs的用法和使用场景
目录结构 1.前言 2.[*args]的用法 2.1.第一步:首先编写这样的函数[test1]. 2.2.第二步:给函数[test1]赋值相关入参值. 2.3.第三步:调用函数[test1],得到以下 ...