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.图形或者网状结构 接下来的 ...
随机推荐
- 常用加密解密算法【RSA、AES、DES、MD5】介绍和使用
内容不转载了,加上链接https://blog.csdn.net/u013565368/article/details/53081195?_t=t
- 学习整理:用webpack4.x构建基本项目
webpack4 在2018年就已经发布了, 相比webpack3,webpack4需要的配置减少了很多,对入口和出口配置都有默认设置可以不用手动设置,但还是要在webpack.config.js中配 ...
- unity之shader
渲染流程分为三个阶段:应用阶段,几何阶段,光栅化阶段. Unity Shader的分类: 使用的是ShaderLab编写unity中的的shader 1 表面着色器 Surface Shader 2 ...
- Java多线程之Runnable与Thread
Java多线程之Thread与Runnable 一.Thread VS Runnable 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:Thread类和 ...
- Python 内存分配时的小秘密
Python 中的sys 模块极为基础而重要,它主要提供了一些给解释器使用(或由它维护)的变量,以及一些与解释器强交互的函数. 本文将会频繁地使用该模块的getsizeof() 方法,因此,我先简要介 ...
- MySQL 5.7 的安装历程
mysql5.7零基础入门级的安装教程: 安装环境:Windows 10, 64 位(联想拯救者R720) 安装版本:mysql-5.7.25-winx64 一.下载 1.进入官网 首先,下载MySQ ...
- Windows上提高工作效率的神器推荐
Everything 下载地址:http://www.voidtools.com/ 功能:硬盘文件搜索,比起电脑自带的文件搜索,效率提高不是一丁半点.而且Everything还支持正则表达式,小巧而快 ...
- Java Builder 模式,你搞明白了么?
Builder 模式定义 Builder 模式中文叫作建造者模式,又叫生成器模式,它属于对象创建型模式,是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.建造者模式是一步一步 ...
- 推荐一个比 ls 命令速度快 100 倍的文件目录浏览神器
本文首发于:微信公众号「运维之美」,公众号 ID:Hi-Linux. 「运维之美」是一个有情怀.有态度,专注于 Linux 运维相关技术文章分享的公众号.公众号致力于为广大运维工作者分享各类技术文章和 ...
- Dart语法学习
Dart语法学习 目录 参考资料 语言特性 关键字 变量与常量 数据类型 运算符 operators 控制流程语句 异常 Exceptions 函数 Function 类 Class 类-方法 类-抽 ...