二叉排序树
1 先看一个需求
给你一个数列 (7, 3, 10, 12, 5, 1, 9),要求能够高效的完成对数据的查询和添加
 
2 解决方案分析
 使用数组
数组未排序, 优点:直接在数组尾添加,速度快。 缺点:查找速度慢. 
数组排序,优点:可以使用二分查找,查找速度快,缺点:为了保证数组有序,在添加新数据时,找到插入位
置后,后面的数据需整体移动,速度慢。
 使用链式存储-链表
不管链表是否有序,查找速度都慢,添加数据速度比数组快,不需要数据整体移动。
 使用二叉排序树
 
3 二叉排序树介绍
  二叉排序树:BST: (Binary Sort(Search) Tree), 对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当
前节点的值小,右子节点的值比当前节点的值大。
  特别说明:如果有相同的值,可以将该节点放在左子节点或右子节点
  比如针对前面的数据 (7, 3, 10, 12, 5, 1, 9) ,对应的二叉排序树为:

4 二叉排序树创建和遍历
一个数组创建成对应的二叉排序树,并使用中序遍历二叉排序树,比如: 数组为 Array(7, 3, 10, 12, 5, 1, 9) , 创
建成对应的二叉排序树为 : 

5 二叉排序树的删除
二叉排序树的删除情况比较复杂,有下面三种情况需要考虑
1) 删除叶子节点 (比如:2, 5, 9, 12)
2) 删除只有一颗子树的节点 (比如:1)
3) 删除有两颗子树的节点. (比如:7, 3,10 )
4) 操作的思路分析

对删除结点的各种情况的思路分析:
第一种情况:
删除叶子节点 (比如:2, 5, 9, 12)
思路
(1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 确定 targetNode 是 parent 的左子结点 还是右子结点
(4) 根据前面的情况来对应删除
左子结点 parent.left = null
右子结点 parent.right = null;
第二种情况: 删除只有一颗子树的节点 比如 1
思路
(1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 确定 targetNode 的子结点是左子结点还是右子结点
(4) targetNode 是 parent 的左子结点还是右子结点
(5) 如果 targetNode 有左子结点
(5). 1 如果 targetNode 是 parent 的左子结点
parent.left = targetNode.left;
(5).2 如果 targetNode 是 parent 的右子结点
parent.right = targetNode.left;
(6) 如果 targetNode 有右子结点
(6).1 如果 targetNode 是 parent 的左子结点
parent.left = targetNode.right;
(6).2 如果 targetNode 是 parent 的右子结点
parent.right = targetNode.righ
情况三 : 删除有两颗子树的节点. (比如:7, 3,10 )
思路
(1) 需求先去找到要删除的结点 targetNode
(2) 找到 targetNode 的 父结点 parent
(3) 从 targetNode 的右子树找到最小的结点
(4) 用一个临时变量,将 最小结点的值保存 temp = 11
(5) 删除该最小结点
(6) targetNode.value = temp
 
6 二叉排序树删除结点的代码实现
package com.lin.binarysorttree_0314;

public class BinarySortTreeTest {

    public static void main(String[] args) {
int[] arr = {7, 3, 10, 12, 5, 1, 9};
BinarySortTree binarySortTree = new BinarySortTree();
for (int i = 0; i < arr.length; i++) {
binarySortTree.add(new SNode(arr[i]));
} binarySortTree.add(new SNode(2));
binarySortTree.infixOrder(); // 删除
System.out.println("***********"); binarySortTree.delNode(2);
binarySortTree.delNode(3);
binarySortTree.delNode(5);
binarySortTree.delNode(7);
binarySortTree.delNode(9);
binarySortTree.delNode(12);
System.out.println("root:" + binarySortTree.getRoot()); binarySortTree.infixOrder();
}
} class BinarySortTree{
private SNode root;
// 查找要删除的节点
public SNode getRoot() {
return root;
}
public SNode searchDelNode(int value) {
if(root == null) {
return null;
} else {
return root.searchDelNode(value);
}
}
// 查找要删除节点的父节点
public SNode searchParent(int value) {
if(root == null) {
return null;
} else {
return root.searchParent(value);
}
}
/**
* @param node 传入的节点(当作二叉排序树的根节点)
* @return 返回的以node为根节点的二叉排序树的最小节点的值
*/
public int delRightTreeMin(SNode node) {
SNode target = node;
// 循环地查找左节点,就会找到最小值
while(target.left != null) {
target = target.left;
}
delNode(target.value);// !!!!
return target.value;// !!!!!
} // 删除节点
public void delNode(int value) {
if(root == null) {
return;
} else {
// 找删除节点
SNode targetNode = searchDelNode(value);
// 没有找到
if(targetNode == null) {
return;
}
// 如果发现当前这棵二叉树只有一个节点
if(root.left == null && root.right == null) {
root = null;
return;
}
// 去找到targetNode的父节点
SNode parent = searchParent(value);
// 如果删除的节点是叶子节点
if(targetNode.left == null && targetNode.right == null) {
// 判断targetNode是父节点的左子节点还是右子节点
if(parent.left != null && parent.left.value == value) {
parent.left = null;
} else if(parent.right != null && parent.right.value == value) {
parent.right = null;
}
} else if(targetNode.left != null && targetNode.right != null) { // 有左右子节点
int delRightTreeMin = delRightTreeMin(targetNode.right);
targetNode.value = delRightTreeMin;
} else {// 只有一个子节点
// 要删除的节点只有左节点
if(targetNode.left != null) {
if(parent != null) {
// 如果targetNode是parent的左子节点
if(parent.left.value == value) {
parent.left = targetNode.left;
} else {
parent.right = targetNode.left;
}
} else {
root = targetNode.left;
}
} else {// 要删除的节点有右子节点
if(parent != null) {
if(parent.left.value == value) {
parent.left = targetNode.right;
} else {
parent.right = targetNode.right;
}
} else {
root = targetNode.right;
}
}
} }
}
// 中序遍历
public void infixOrder() {
if(root == null) {
System.out.println("空树!");
} else {
root.infixOrder();
}
}
// 添加
public void add(SNode node) {
if(root == null) {
root = node;
} else {
root.add(node);
}
}
} class SNode{
protected int value;
protected SNode left;
protected SNode right; public SNode(int value) {
// TODO Auto-generated constructor stub
this.value = value;
} @Override
public String toString() {
// TODO Auto-generated method stub
return "Node = [value = " + value + "]";
} // 添加节点
public void add(SNode node) {
if(node == null) {
return;
}
if(node.value < this.value) {
if(this.left == null) {
this.left = node;
} else {
this.left.add(node);
}
} else {
if(this.right == null) {
this.right = node;
} else {
this.right.add(node);
}
}
}
// 中序遍历
public void infixOrder() {
if(this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if(this.right != null) {
this.right.infixOrder();
}
}
// 查找要删除的节点
public SNode searchDelNode(int value) {
if(this.value == value) {
return this;
} else if(this.value > value) {
// 如果左子节点为空
if(this.left == null) {
return null;
}
return this.left.searchDelNode(value);
} else {
if(this.right == null) {
return null;
}
return this.right.searchDelNode(value);
}
}
// 查找要删除节点的父节点, 如果没有则返回null
public SNode searchParent(int value) {
if(( this.left != null && this.left.value == value)
|| ( this.right != null && this.right.value == value )) {
return this;
} else {
// 如果查找的值小于当前节点的值,并且当前节点的左子节点不为空
if(value < this.value && this.left != null) {
return this.left.searchParent(value);
} else if(value >= this.value && this.right != null) {
return this.right.searchParent(value);
} else {
return null;
}
}
} }

仅供参考,有错误还请指出!

有什么想法,评论区留言,互相指教指教。

觉得不错的可以点一下右边的推荐哟

Java 树结构实际应用 三(二叉排序树)的更多相关文章

  1. Java 处理 XML 的三种主流技术及介绍

    Java 处理 XML 的三种主流技术及介绍 原文地址:https://www.ibm.com/developerworks/cn/xml/dm-1208gub/ XML (eXtensible Ma ...

  2. java解析xml的三种方法

    java解析XML的三种方法 1.SAX事件解析 package com.wzh.sax; import org.xml.sax.Attributes; import org.xml.sax.SAXE ...

  3. 20145213《Java程序设计》实验三敏捷开发与XP实践

    20145213<Java程序设计>实验三敏捷开发与XP实践 实验要求 1.XP基础 2.XP核心实践 3.相关工具 实验内容 1.敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法 ...

  4. 20145213《Java程序设计》第三周学习总结

    20145213<Java程序设计>第三周学习总结 教材学习内容总结 正所谓距离产生美,上周我还倾心于Java表面的基础语法.其简单的流程结构,屈指可数的基本类型分类,早已烂熟于心的运算符 ...

  5. 20145206《Java程序设计》实验三实验报告

    20145206<Java程序设计>实验三实验报告 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运 ...

  6. 20145308刘昊阳 《Java程序设计》实验三 敏捷开发与XP实践 实验报告

    20145308刘昊阳 <Java程序设计>实验三 敏捷开发与XP实践 实验报告 实验名称 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 统计的PSP(Personal ...

  7. 20145330《Java程序设计》第三周学习总结

    20145330 <Java程序设计>第三周学习总结 第三周知识的难度已经逐步上升,并且一周学习两章学习压力也逐渐加大,需要更高效率的来完成学习内容,合理安排时间. 类与对象 对象(Obj ...

  8. 20145337《Java程序设计》第三周学习总结

    20145337 <Java程序设计>第三周学习总结 教材学习内容总结 类与对象 类与对象的关系:要产生对象必须先定义类,类是对象的设计图,对象是类的实例.我觉得在视频中对类与对象关系的描 ...

  9. 20145320《Java程序设计》第三次实验报告

    20145320<Java程序设计>第三次实验报告 北京电子科技学院(BESTI)实验报告 课程:Java程序设计 班级:1453 指导教师:娄嘉鹏 实验日期:2016.04.22 15: ...

随机推荐

  1. C++中二维数组作为函数参数

    在平时,我们经常会遇到将整个数组作为函数参数的情况,一维数组的情况,就是用数组名当形参和实参,传递的是数组的首地址.二维数组我们用的也很多,但是总是有各种问题,今天我总结一下 有个很重要的一点,字符串 ...

  2. hdu 5883

    Alice is planning her travel route in a beautiful valley. In this valley, there are NN lakes, and MM ...

  3. 80行Python代码搞定全国区划代码

    微信搜索:码农StayUp 主页地址:https://gozhuyinglong.github.io 源码分享:https://github.com/gozhuyinglong/blog-demos ...

  4. Linux内核实现透视---软中断&Tasklet

    软中断 首先明确一个概念软中断(不是软件中断int n).总来来说软中断就是内核在启动时为每一个内核创建了一个特殊的进程,这个进程会不停的poll检查是否有软中断需要执行,如果需要执行则调用注册的接口 ...

  5. WebIDE All In One

    WebIDE All In One web IDE Visual Studio Code vscode Code editing Redefined. Free. Built on open sour ...

  6. Web Components All In One

    Web Components All In One Web Components https://www.webcomponents.org/ HTML Template Custom Element ...

  7. svn conflict & svn cleanup

    svn conflict & svn cleanup OK $ svn --help $ svn cleanup Tree Conflicts https://tortoisesvn.net/ ...

  8. HTML5 & custom element & template

    HTML5 & custom element & template template https://codepen.io/xgqfrms/pen/eYYExvp https://cs ...

  9. FileReader, readAsText

    readastext filereader FileReader.readAsText() https://developer.mozilla.org/zh-CN/docs/Web/API/FileR ...

  10. 自定义Edit 样式 简便写法

    1 <?xml version="1.0" encoding="utf-8"?> 2 <selector xmlns:android=&quo ...