java数据结构——二叉树(BinaryTree)
前面我们已经学习了一些线性结构的数据结构和算法,接下来我们开始学习非线性结构的内容。
二叉树
前面显示增、删、查、遍历方法,完整代码在最后面。
/**
* 为什么我们要学习树结构。
* 1、有序数组插入数据项和删除数据项太慢。
* 2、链表查找数据太慢。
* 3、在树中能非常快速的查找、插入、删除数据,结合了有序数组和链表的优点
* 4、暂时还不知道
*/
结点打包类
public class BinaryTree {
//数据项(对象什么都可以)
public long data;
//左孩子
public BinaryTree leftChiled;
//右孩子
public BinaryTree rightChiled; public BinaryTree(int value) {
this.data = value;
} }
public void add(int value) {
// 封装结点
BinaryTree newnode = new BinaryTree(value); BinaryTree parent;// 引用父节点 BinaryTree current = root;// current引用根结点 if (root == null) {// 如果root为null,也就是第一次插入
root = newnode;
return;
} else {
while (true) { parent = current;// 父节点指向指向当前节点,保存上一个结点
if (current.data > value) {
current = current.leftChiled;
if (current == null) {
parent.leftChiled = newnode;
return;
}
} else {
current = current.rightChiled; if (current == null) {
parent.rightChiled = newnode;
return;
}
} }
}
}
添加方法
一、删除节点是二叉树操作中最复杂的。在删除之前首先要查找要删的节点。找到节点后,这个要删除的节点可能会有三种情况需要考虑。
public boolean delete(long value) {// 删除
BinaryTree current = root;// current保存根结点
BinaryTree parent = root;// parent保存parent的父节点
boolean isLeftchild = true;
while (current.data != value) {
parent = current;
// 进行比较,比较当前值和查找值的大小
if (current.data > value) {
current = current.leftChiled;
isLeftchild = true;// true为左子树
} else {
current = current.rightChiled;
isLeftchild = false;
}
if (current == null) {
return false;
}
}
if (current.leftChiled == null && current.rightChiled == null) {// 第1种情况
if (isLeftchild) {
parent.leftChiled = null;
} else {
parent.rightChiled = null;
}
} else if (current.rightChiled == null) {// 第2种情况
if (current == root) {
root = current.leftChiled;
} else if (isLeftchild) {
parent.leftChiled = current.leftChiled;
} else {
parent.rightChiled = current.leftChiled;
}
} else if (current.leftChiled == null) {
if (current == root) {
root = current.rightChiled;
} else if (isLeftchild) {
parent.leftChiled = current.rightChiled;
} else {
parent.rightChiled = current.rightChiled;
}
} else {// 第3种情况
BinaryTree successor = getSuccessor(current);// 根结点开始,successor存放中序后继结点
if (current == root) {// 替换工作
root = successor;
} else if (isLeftchild) {// 要删除的父节点的左子节点
parent.leftChiled = successor;
} else {// 要删除的父节点的右子节点
parent.rightChiled = successor;
}
successor.leftChiled = current.leftChiled;// 中序后继结点引用删除的左边的结点
} return true;
} public BinaryTree getSuccessor(BinaryTree delBin) {// 找中序后继结点方法
// delBin为要删除的结点
BinaryTree successor = delBin;// successor为查找的中序后继结点
BinaryTree successorParent = delBin; // successor的父节点
BinaryTree current = delBin.rightChiled; // 当前开始遍历的结点 while (current != null) {// 这里完成elBin.rightChiled是叶子结点
successorParent = successor;// successorParent保存上一个successor的引用
successor = current;// 循环完成以后,successor保存的就是中序后继结点
current = current.leftChiled;
}
// 中序后继结点有两种情况,就是delBin.rightChiled是否为叶子结点的两种情况 if (successor != delBin.rightChiled) {// elBin.rightChiled不是叶子结点,中序后继结点是左边的
successorParent.leftChiled = successor.rightChiled;// 中序后继结点后面肯定只有右子节点
successor.rightChiled = delBin.rightChiled;// 中序后继结点的右子节点指向要删除的右边的结点
// successor.rightChiled指向要删除的rightChiled
// 交换成功
}
return successor; }
删除方法
二、
public BinaryTree find(int value) {// 查找
// 引用当前结点,从根结点开始
BinaryTree current = root;
// 循环,只要查找值不等于当前结点的数据项
while (current.data != value) {
// 进行比较,比较当前值和查找值的大小
if (current.data > value) {
current = current.leftChiled;
} else {
current = current.rightChiled;
}
if (current == null) {
return null;
} }
return current;
}
查找方法
遍历二叉树,有3种遍历方法。其中,中序遍历最为常用,因为可以让特定的数据排序输出,前面我们已经学习了递归方法,接下来我们也使用递归方法实现。
(1)访问根结点
(2)前序遍历左子树
(3)前序遍历右子树
public void frontOrder(BinaryTree localBin) {// 前序
if (localBin != null) {// 递归结束条件
System.out.println(localBin.data);
frontOrder(localBin.leftChiled);
frontOrder(localBin.rightChiled);
}
}
前序遍历
中序遍历。
(1)中序遍历左子树
(2)访问根结点
(3)中序遍历右子树
public void middleOrder(BinaryTree localBin) {// 前序
if (localBin != null) {// 递归结束条件
middleOrder(localBin.leftChiled);
System.out.println(localBin.data);
middleOrder(localBin.rightChiled);
}
}
中序遍历
后序遍历。
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根结点
public void endOrder(BinaryTree localBin) {// 前序
if (localBin != null) {// 递归结束条件
endOrder(localBin.leftChiled);
endOrder(localBin.rightChiled);
System.out.println(localBin.data);
}
}
后序遍历
前辈的头发秃光不是没有原因的,哈哈哈。
package binarytree; public class TestTree {
// 根结点
public BinaryTree root; public static void main(String[] args) {
TestTree tt = new TestTree();
tt.add(10);
tt.add(5);
tt.add(4);
tt.add(6);
tt.add(12);
tt.add(11);
tt.add(14);
tt.add(13); tt.middleOrder(tt.root);
tt.delete(10);
System.out.println();
tt.middleOrder(tt.root); } public void frontOrder(BinaryTree localBin) {// 前序
if (localBin != null) {// 递归结束条件
System.out.print(localBin.data + " ");
frontOrder(localBin.leftChiled);
frontOrder(localBin.rightChiled);
}
} public void middleOrder(BinaryTree localBin) {// 中序
if (localBin != null) {// 递归结束条件
middleOrder(localBin.leftChiled);
System.out.print(localBin.data + " ");
middleOrder(localBin.rightChiled);
}
} public void endOrder(BinaryTree localBin) {// 后序
if (localBin != null) {// 递归结束条件
endOrder(localBin.leftChiled);
endOrder(localBin.rightChiled);
System.out.print(localBin.data + " ");
}
} public void add(int value) {
// 封装结点
BinaryTree newnode = new BinaryTree(value); BinaryTree parent;// 引用父节点 BinaryTree current = root;// current引用根结点 if (root == null) {// 如果root为null,也就是第一次插入
root = newnode;
return;
} else {
while (true) { parent = current;// 父节点指向指向当前节点,保存上一个结点
if (current.data > value) {
current = current.leftChiled;
if (current == null) {
parent.leftChiled = newnode;
return;
}
} else {
current = current.rightChiled; if (current == null) {
parent.rightChiled = newnode;
return;
}
} }
}
} public BinaryTree find(int value) {// 查找
// 引用当前结点,从根结点开始
BinaryTree current = root;
// 循环,只要查找值不等于当前结点的数据项
while (current.data != value) {
// 进行比较,比较当前值和查找值的大小
if (current.data > value) {
current = current.leftChiled;
} else {
current = current.rightChiled;
}
if (current == null) {
return null;
} }
return current;
} public boolean delete(long value) {// 删除
BinaryTree current = root;// current保存根结点
BinaryTree parent = root;// parent保存parent的父节点
boolean isLeftchild = true;
while (current.data != value) {
parent = current;
// 进行比较,比较当前值和查找值的大小
if (current.data > value) {
current = current.leftChiled;
isLeftchild = true;// true为左子树
} else {
current = current.rightChiled;
isLeftchild = false;
}
if (current == null) {
return false;
}
}
if (current.leftChiled == null && current.rightChiled == null) {// 第1种情况
if (isLeftchild) {
parent.leftChiled = null;
} else {
parent.rightChiled = null;
}
} else if (current.rightChiled == null) {// 第2种情况
if (current == root) {
root = current.leftChiled;
} else if (isLeftchild) {
parent.leftChiled = current.leftChiled;
} else {
parent.rightChiled = current.leftChiled;
}
} else if (current.leftChiled == null) {
if (current == root) {
root = current.rightChiled;
} else if (isLeftchild) {
parent.leftChiled = current.rightChiled;
} else {
parent.rightChiled = current.rightChiled;
}
} else {// 第3种情况
BinaryTree successor = getSuccessor(current);// 根结点开始,successor存放中序后继结点
if (current == root) {// 替换工作
root = successor;
} else if (isLeftchild) {// 要删除的父节点的左子节点
parent.leftChiled = successor;
} else {// 要删除的父节点的右子节点
parent.rightChiled = successor;
}
successor.leftChiled = current.leftChiled;// 中序后继结点引用删除的左边的结点
} return true;
} public BinaryTree getSuccessor(BinaryTree delBin) {// 找中序后继结点方法
// delBin为要删除的结点
BinaryTree successor = delBin;// successor为查找的中序后继结点
BinaryTree successorParent = delBin; // successor的父节点
BinaryTree current = delBin.rightChiled; // 当前开始遍历的结点 while (current != null) {// 这里完成elBin.rightChiled是叶子结点
successorParent = successor;// successorParent保存上一个successor的引用
successor = current;// 循环完成以后,successor保存的就是中序后继结点
current = current.leftChiled;
}
// 中序后继结点有两种情况,就是delBin.rightChiled是否为叶子结点的两种情况 if (successor != delBin.rightChiled) {// elBin.rightChiled不是叶子结点,中序后继结点是左边的
successorParent.leftChiled = successor.rightChiled;// 中序后继结点后面肯定只有右子节点
successor.rightChiled = delBin.rightChiled;// 中序后继结点的右子节点指向要删除的右边的结点
// successor.rightChiled指向要删除的rightChiled
// 交换成功
}
return successor; }
}
complete code
java数据结构——二叉树(BinaryTree)的更多相关文章
- (2)Java数据结构--二叉树 -和排序算法实现
=== 注释:此人博客对很多个数据结构类都有讲解-并加以实例 Java API —— ArrayList类 & Vector类 & LinkList类Java API —— BigDe ...
- Java数据结构——二叉树
前序遍历——根 左 右 中序遍历——左 根 右 后序遍历——左 右 根 //================================================= // File Name ...
- Java数据结构——二叉树 增加、删除、查询
//二叉树系统 public class BinarySystem { public static void main(String[] args) { BinaryDomain root = nul ...
- Java数据结构——二叉树的遍历(汇总)
二叉树的遍历分为深度优先遍历(DFS)和广度优先遍历(BFS) DFS遍历主要有: 前序遍历 中序遍历 后序遍历 一.递归实现DFSNode.java: public class Node { pri ...
- java数据结构(二叉树)
Node节点: public class Node { public long data; public String sData; public Node leftChild; public Nod ...
- Java数据结构——二叉树节点的增删改查、获取深度及最大最小值
一.查找最大值 // 查找最大值 public static Node maxNode() { Node node = root; Node maxNode = node; while (node ! ...
- Java数据结构和算法(四)赫夫曼树
Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...
- Java数据结构之树和二叉树(2)
从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来 ...
- Java数据结构之树和二叉树
从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...
随机推荐
- LInux系统@安装CentOS7虚拟机
安装Centos7虚拟机 1.打开VMware,点击创建新的虚拟机(至关重要) 2.选择自定义配置,点击下一步 3.选择虚拟机硬件兼容性<Workstation 12.0>,点击下一步 4 ...
- 2019牛客暑期多校训练营(第十场)J - Wood Processing (斜率优化DP)
>传送门< 题意 $n$个宽度为$w_{i}$,高为$h_{i}$ 的 木块,要求分成$k$组,对于每组内的所有木块,高度都变为组内最低木块的高度,宽度保持不变,求变化的最小面积. 分析 ...
- java学习之- 线程继承Thread类
标签(空格分隔): 线程 在java.lang包中有个Thread子类,大家可以自行查阅文档,及范例: 如何在自定义的代码中,自定义一个线程呢? 1.通过对api的查找,java已经提供了对线程这类事 ...
- Nacos(八):Nacos持久化
参考和感谢 Spring Cloud Alibaba基础教程:Nacos的数据持久化 前言 前景回顾: Nacos(七):Nacos共享配置 Nacos(六):多环境下如何"管理" ...
- 解决npm报错:Module build failed: TypeError: this.getResolve is not a function
1.sass-loader的版本过高导致的编译错误,当前最高版本是8.x,需要退回到7.3.1 运行: npm uninstall sass-loader --save-dev(卸载当前版本) npm ...
- SQlServer 数据库表名称,字段比较
项目中一般分测试环境(QAS),生产环境(PRD),当我们的项目经历了一次周期跨度较长的更新后,当我们发布到生产环境时,首要的任务是将新增的表,字段更新到生产数据库.很多时候,当我们发布更新的时候,已 ...
- Codeforces 832 D Misha, Grisha and Underground
Misha, Grisha and Underground 题意:Misha 和 Grisha 是2个很喜欢恶作剧的孩子, 每天早上 Misha 会从地铁站 s 通过最短的路到达地铁站 f, 并且在每 ...
- Atcoder F - Mirrored(思维+搜索)
题目链接:http://arc075.contest.atcoder.jp/tasks/arc075_d 题意:求rev(N)=N+D的个数,rev表示取反.例如rev(123)=321 题解:具体看 ...
- 深入浅出TypeScript(5)- 在React项目中使用TypeScript
前言 在第二小节中,我们讨论了利用TypeScript创建Web项目的实现,在本下节,我们讨论一下如何结合React创建一个具备TypeScript类型的应用项目. 准备 Webpack配置在第二小节 ...
- iphone不支持(格式:2016-02-26 09:12)的格式时间需要转换成:(格式:2016/02/26 09:12)
function strToTime(str) {return Date.parse(str.replace(/-/g, "/"));} 苹果手机不支持创建这种时间格式 需要转化一 ...