前面我们已经学习了一些线性结构的数据结构和算法,接下来我们开始学习非线性结构的内容。

二叉树

前面显示增、删、查、遍历方法,完整代码在最后面。

/**
 * 为什么我们要学习树结构。
 * 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;
}
} }
}
}

添加方法

 

一、删除节点是二叉树操作中最复杂的。在删除之前首先要查找要删的节点。找到节点后,这个要删除的节点可能会有三种情况需要考虑。

1.该节点是叶子节点,没有子节点。
要删除叶节点,只需要改变该节点的父节点的引用值,将指向该节点的引用设置为null就可以了。
2.该节点有一个子节点。
改变父节点的引用,将其直接指向要删除节点的子节点。
3.该节点有两个子节点。
要删除有两个子节点的节点,就需要使用它的中序后继来替代该节点。
费我九牛二虎之力还是给整出来了。
 
 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)的更多相关文章

  1. (2)Java数据结构--二叉树 -和排序算法实现

    === 注释:此人博客对很多个数据结构类都有讲解-并加以实例 Java API —— ArrayList类 & Vector类 & LinkList类Java API —— BigDe ...

  2. Java数据结构——二叉树

    前序遍历——根 左 右 中序遍历——左 根 右 后序遍历——左 右 根 //================================================= // File Name ...

  3. Java数据结构——二叉树 增加、删除、查询

    //二叉树系统 public class BinarySystem { public static void main(String[] args) { BinaryDomain root = nul ...

  4. Java数据结构——二叉树的遍历(汇总)

    二叉树的遍历分为深度优先遍历(DFS)和广度优先遍历(BFS) DFS遍历主要有: 前序遍历 中序遍历 后序遍历 一.递归实现DFSNode.java: public class Node { pri ...

  5. java数据结构(二叉树)

    Node节点: public class Node { public long data; public String sData; public Node leftChild; public Nod ...

  6. Java数据结构——二叉树节点的增删改查、获取深度及最大最小值

    一.查找最大值 // 查找最大值 public static Node maxNode() { Node node = root; Node maxNode = node; while (node ! ...

  7. Java数据结构和算法(四)赫夫曼树

    Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...

  8. Java数据结构之树和二叉树(2)

    从这里始将要继续进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来 ...

  9. Java数据结构之树和二叉树

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

随机推荐

  1. 林大妈的CSS知识清单(一)添加样式

    回顾CSS选择符,学习接入样式的更多方式. 一.选择符 1. 种类 ① 类型选择符:直接的HTML标签名,例如: body.p.div 等: ② 后代选择符:空格,例如: div p 选择div中的所 ...

  2. deepin 15.11 安装 pyenv

    GitHub:官方环境:https://github.com/pyenv/pyenv/wiki/Common-build-problems GitHub:官方文档:https://github.com ...

  3. Java多线程之线程协作

    Java多线程之线程协作 一.前言 上一节提到,如果有一个线程正在运行synchronized 方法,那么其他线程就无法再运行这个方法了.这就是简单的互斥处理. 假如我们现在想执行更加精确的控制,而不 ...

  4. matplotlib绘制矢量图像(svg),pdf and ps文件

    机器学习的过程中处理数据,会遇到数据可视化的问题. 大部分都是利用python的matplotlib库进行数据的可视化处理. plt.show() 默认都是输出.png文件,图片只要稍微放大一点,就糊 ...

  5. P2564 [SCOI2009]生日礼物 贪心

    https://www.luogu.org/problemnew/show/P2564) 题意 有n个珠子,包括k中颜色,找出长度最小的一个区间,使得这个区间中包含所有的颜色. 思路 把n个珠子按照位 ...

  6. 深入浅出理解EdgeBoard中NHWC数据格式

    摘要: 在深度学习中,为了提升数据传输带宽和计算性能,经常会使用NCHW.NHWC和CHWN数据格式,它们代表Image或Feature Map等的逻辑数据格式(可以简单理解为数据在内存中的存放顺序) ...

  7. XML的相关基础知识分享

    XML和Json是两种最常用的在网络中数据传输的数据序列化格式,随着时代的变迁,XML序列化用于网络传输也逐渐被Json取代,前几天,单位系统集成开发对接接口时,发现大部分都用的WebService技 ...

  8. 3、pytest中文文档--编写断言

    目录 编写断言 使用assert编写断言 编写触发期望异常的断言 特殊数据结构比较时的优化 为失败断言添加自定义的说明 关于断言自省的细节 复写缓存文件 去使能断言自省 编写断言 使用assert编写 ...

  9. Python入门基础:七段数码管绘制

    1.在学习Python的过程中,运用所学的一些基础知识,进行一些简单的编程,可以收获很多乐趣.在生活中,LED灯无处不在,荧幕显示的广告词,给我们呈现出动态的视觉效果.下面,则以最简单的显示日期为例, ...

  10. Python3实战Spark大数据分析及调度 (网盘分享)

    Python3实战Spark大数据分析及调度 搜索QQ号直接加群获取其它学习资料:715301384 部分课程截图: 链接:https://pan.baidu.com/s/12VDmdhN4hr7yp ...