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

二叉树

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

/**
 * 为什么我们要学习树结构。
 * 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. LInux系统@安装CentOS7虚拟机

    安装Centos7虚拟机 1.打开VMware,点击创建新的虚拟机(至关重要) 2.选择自定义配置,点击下一步 3.选择虚拟机硬件兼容性<Workstation 12.0>,点击下一步 4 ...

  2. 2019牛客暑期多校训练营(第十场)J - Wood Processing (斜率优化DP)

    >传送门< 题意 $n$个宽度为$w_{i}$,高为$h_{i}$ 的 木块,要求分成$k$组,对于每组内的所有木块,高度都变为组内最低木块的高度,宽度保持不变,求变化的最小面积. 分析 ...

  3. java学习之- 线程继承Thread类

    标签(空格分隔): 线程 在java.lang包中有个Thread子类,大家可以自行查阅文档,及范例: 如何在自定义的代码中,自定义一个线程呢? 1.通过对api的查找,java已经提供了对线程这类事 ...

  4. Nacos(八):Nacos持久化

    参考和感谢 Spring Cloud Alibaba基础教程:Nacos的数据持久化 前言 前景回顾: Nacos(七):Nacos共享配置 Nacos(六):多环境下如何"管理" ...

  5. 解决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 ...

  6. SQlServer 数据库表名称,字段比较

    项目中一般分测试环境(QAS),生产环境(PRD),当我们的项目经历了一次周期跨度较长的更新后,当我们发布到生产环境时,首要的任务是将新增的表,字段更新到生产数据库.很多时候,当我们发布更新的时候,已 ...

  7. Codeforces 832 D Misha, Grisha and Underground

    Misha, Grisha and Underground 题意:Misha 和 Grisha 是2个很喜欢恶作剧的孩子, 每天早上 Misha 会从地铁站 s 通过最短的路到达地铁站 f, 并且在每 ...

  8. Atcoder F - Mirrored(思维+搜索)

    题目链接:http://arc075.contest.atcoder.jp/tasks/arc075_d 题意:求rev(N)=N+D的个数,rev表示取反.例如rev(123)=321 题解:具体看 ...

  9. 深入浅出TypeScript(5)- 在React项目中使用TypeScript

    前言 在第二小节中,我们讨论了利用TypeScript创建Web项目的实现,在本下节,我们讨论一下如何结合React创建一个具备TypeScript类型的应用项目. 准备 Webpack配置在第二小节 ...

  10. iphone不支持(格式:2016-02-26 09:12)的格式时间需要转换成:(格式:2016/02/26 09:12)

    function strToTime(str) {return Date.parse(str.replace(/-/g, "/"));} 苹果手机不支持创建这种时间格式 需要转化一 ...